Lavorare con proxy in Deno e Bun può sembrare immediato, ma la fetch() nativa di JavaScript ignora i proxy per impostazione predefinita. Se stai costruendo pipeline di web scraping, monitoraggio SERP o automazione su larga scala, devi sapere come configurare un proxy in Deno e Bun a livello di runtime, come gestire geo-targeting e sessioni sticky, e quali insidie aspettarsi in produzione. Questa guida risolve esattamente quel problema con esempi di codice completi.
JavaScript moderno ha due nuovi runtime — Deno e Bun — che offrono approcci diversi al problema. Vedremo entrambi, con snippet pronti da eseguire che usano il gateway gate.proxyhat.com di ProxyHat.
Perché fetch() ignora i proxy per default
La fetch() standard è definita dalla WHATWG Fetch Specification, che non include un concetto nativo di proxy HTTP. I browser delegano il routing dei proxy al sistema operativo o alle impostazioni di rete. I runtime server-side come Node.js, Deno e Bun hanno dovuto costruire soluzioni proprie sopra o accanto all'implementazione standard.
In pratica, se scrivi fetch("https://example.com") in Deno o Bun senza configurazione aggiuntiva, la richiesta esce direttamente dal tuo IP. Per un scraper o un tool di automazione, questo significa che dopo poche centinaia di richieste il tuo IP viene bloccato con un errore 403 o un challenge CAPTCHA.
Le variabili d'ambiente HTTP_PROXY e HTTPS_PROXY sono una soluzione parziale: alcuni runtime le leggono automaticamente, altri no. La strategia migliore è la configurazione esplicita per-client, che ti dà controllo granulare su geo-targeting, rotazione IP e sessioni sticky.
Deno proxy: usare Deno.createHttpClient
Deno espone Deno.createHttpClient(), che restituisce un client HTTP personalizzato. Puoi passarlo a fetch() tramite l'opzione { client }. Questo è il modo canonico per configurare un Deno proxy a livello di singola richiesta.
Esempio base: proxy HTTP con autenticazione
// deno run --allow-net proxy_basic.ts
const proxyUrl = "http://user:pass@gate.proxyhat.com:8080";
const client = Deno.createHttpClient({
proxy: {
url: proxyUrl,
// basicAuth è opzionale se le credenziali sono già nell'URL
},
});
try {
const res = await fetch("https://httpbin.org/ip", { client });
const body = await res.json();
console.log("IP tramite proxy:", body.origin);
} catch (err) {
console.error("Errore fetch:", err);
} finally {
client.close();
}
Nota l'uso di client.close() nel blocco finally: Deno richiede la chiusura esplicita del client per liberare le risorse di rete. Dimenticarsene causa leak di connessioni sotto carico.
Geo-targeting e sessioni sticky nel username
ProxyHat codifica geo-targeting e sessioni sticky direttamente nel nome utente. Non servono header aggiuntivi:
// Proxy USA con sessione sticky
const proxyUrl = "http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080";
const client = Deno.createHttpClient({
proxy: { url: proxyUrl },
});
const res = await fetch("https://httpbin.org/ip", { client });
console.log(await res.json());
client.close();
Il flag country-US instrada il traffico attraverso un IP residenziale statunitense. Il flag session-abc123 mantiene lo stesso IP di uscita per tutte le richieste che usano quel identificatore — essenziale per login, carrelli e-commerce o flussi multi-pagina.
SOCKS5 su porta 1080
Per traffico che beneficia del protocollo SOCKS5 (tunneling a livello TCP, utile per evitare overhead HTTP CONNECT), ProxyHat espone la porta 1080:
const socksUrl = "socks5://user-country-DE-session-xyz789:pass@gate.proxyhat.com:1080";
const client = Deno.createHttpClient({
proxy: { url: socksUrl },
});
const res = await fetch("https://httpbin.org/ip", { client });
console.log(await res.text());
client.close();
Bun fetch proxy: configurazione one-line
Bun rende le cose ancora più semplici: l'opzione proxy è accettata direttamente da fetch(). Questo rende Bun fetch proxy la configurazione più concisa tra i runtime moderni.
// bun run proxy_basic.ts
const proxy = "http://user:pass@gate.proxyhat.com:8080";
try {
const res = await fetch("https://httpbin.org/ip", {
proxy,
});
const body = await res.json();
console.log("IP tramite proxy:", body.origin);
} catch (err) {
console.error("Errore fetch Bun:", err);
}
Niente client da chiudere, niente oggetti intermedi. Bun gestisce il ciclo di vita della connessione internamente. Per geo-targeting, la sintassi nel username è identica:
const proxy = "http://user-country-IT-session-sess01:pass@gate.proxyhat.com:8080";
const res = await fetch("https://httpbin.org/headers", { proxy });
console.log(await res.json());
Variabili d'ambiente HTTP_PROXY e HTTPS_PROXY
Entrambi i runtime supportano HTTP_PROXY e HTTPS_PROXY come variabili d'ambiente. Questo è utile per script CLI o container Docker dove non vuoi codificare le credenziali nel sorgente:
# Imposta le variabili d'ambiente
export HTTP_PROXY="http://user-country-GB:pass@gate.proxyhat.com:8080"
export HTTPS_PROXY="http://user-country-GB:pass@gate.proxyhat.com:8080"
# Esegui lo script
bun run scraper.ts
Quando preferire la configurazione per-client: se hai bisogno di proxy diversi per richieste diverse (rotazione IP, geo-targeting dinamico), la configurazione esplicita è obbligatoria. Le variabili d'ambiente sono globali e non supportano override per-request. Inoltre, le credenziali nelle variabili d'ambiente sono visibili a tutti i processi figlio — un rischio di sicurezza in ambienti multi-tenant.
Proxy residenziali per target ad alta resistenza
I proxy datacenter sono economici ma facili da rilevare: molti siti bloccano interi range ASN associati a provider cloud. I proxy residenziali usano IP assegnati a ISP reali, rendendo il traffico indistinguibile da quello di un utente genuino. Questo è critico per SERP tracking, price monitoring su e-commerce e qualsiasi sito protetto da sistemi anti-bot come Cloudflare o PerimeterX.
Esempio: rotazione di sessioni sticky con Promise.all
Il pattern seguente crea un pool di sessioni sticky, ognuna con un IP residenziale diverso, ed esegue richieste concorrenti con timeout tramite AbortController:
// bun run pool_scraper.ts
const PROXY_BASE = "http://user-country-US-session-";
const PROXY_PASS = "pass";
const GATE = "gate.proxyhat.com:8080";
const urls = [
"https://httpbin.org/ip?n=1",
"https://httpbin.org/ip?n=2",
"https://httpbin.org/ip?n=3",
"https://httpbin.org/ip?n=4",
"https://httpbin.org/ip?n=5",
];
async function fetchWithProxy(url: string, sessionId: string): Promise<string> {
const proxy = `${PROXY_BASE}${sessionId}:${PROXY_PASS}@${GATE}`;
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 15000);
try {
const res = await fetch(url, {
proxy,
signal: controller.signal,
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
return `Session ${sessionId}: ${data.origin}`;
} catch (err) {
return `Session ${sessionId}: ERROR - ${err.message}`;
} finally {
clearTimeout(timeout);
}
}
// Genera 5 sessioni sticky univoche
const sessions = Array.from({ length: 5 }, (_, i) => `sess-${Date.now()}-${i}`);
const results = await Promise.all(
urls.map((url, i) => fetchWithProxy(url, sessions[i]))
);
results.forEach((r) => console.log(r));
Questo codice esegue 5 richieste concorrenti, ciascuna con un IP residenziale USA diverso. Il timeout di 15 secondi tramite AbortController previene stalli infiniti. Con 100 sessioni concorrenti e un tasso di successo del 99% su proxy residenziali, puoi processare migliaia di richieste al minuto senza un singolo IP che si brucia.
Production tips: retry, backoff, CA personalizzate
Retry con backoff esponenziale
In produzione, anche i migliori proxy falliscono occasionalmente. Un retry con backoff esponenziale è essenziale:
// deno run --allow-net retry_scraper.ts
const proxyUrl = "http://user-country-FR:pass@gate.proxyhat.com:8080";
async function fetchWithRetry(
url: string,
maxRetries = 3,
baseDelay = 1000
): Promise<Response> {
let lastError: Error | null = null;
for (let attempt = 0; attempt < maxRetries; attempt++) {
const client = Deno.createHttpClient({ proxy: { url: proxyUrl } });
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000);
try {
const res = await fetch(url, {
client,
signal: controller.signal,
});
if (res.ok) return res;
if (res.status === 429 || res.status >= 500) {
throw new Error(`Retryable: ${res.status}`);
}
throw new Error(`Non-retryable: ${res.status}`);
} catch (err) {
lastError = err;
const delay = baseDelay * Math.pow(2, attempt) + Math.random() * 500;
console.warn(`Tentativo ${attempt + 1} fallito, retry in ${Math.round(delay)}ms`);
await new Promise((r) => setTimeout(r, delay));
} finally {
clearTimeout(timeout);
client.close();
}
}
throw lastError;
}
const res = await fetchWithRetry("https://httpbin.org/status/200");
console.log("Successo dopo retry:", res.status);
Riprova solo su 429 (rate limit) e 5xx (errori server). Gli errore 403 o 404 indicano problemi che un retry non risolverà.
CA personalizzate in Deno con caCerts
Se il tuo ambiente usa certificati custom (es. un proxy MITM aziendale), Deno ti permette di passare CA certificate espliciti:
const caCert = await Deno.readTextFile("./custom-ca.pem");
const client = Deno.createHttpClient({
proxy: { url: "http://user:pass@gate.proxyhat.com:8080" },
caCerts: [caCert],
});
const res = await fetch("https://httpbin.org/ip", { client });
console.log(await res.json());
client.close();
Questo è particolarmente utile in pipeline CI/CD dove il certificato di sistema potrebbe non essere aggiornato.
Confronto: configurazione proxy Deno vs Bun vs Node SDK
| Caratteristica | Deno | Bun | ProxyHat Node SDK |
|---|---|---|---|
| Configurazione proxy | createHttpClient({ proxy }) + { client } |
fetch(url, { proxy }) |
Wrapper automatico |
| SOCKS5 support | Sì (nativo) | Sì (nativo) | Sì |
| Chiusura esplicita | Sì (client.close()) |
No (automatico) | No (gestito dal SDK) |
| CA personalizzate | caCerts in createHttpClient |
Non supportato nativamente | Dipende dal runtime |
| Compatibilità runtime | Deno only | Bun only | Deno + Bun + Node |
| Rotazione IP built-in | Manuale | Manuale | Sì |
ProxyHat Node SDK: funziona sotto Deno e Bun
Il ProxyHat SDK per Node.js è compatibile con entrambi i runtime grazie alla loro compatibilità con le API Node. Questo ti dà un'astrazione che gestisce rotazione, retry e sessioni sticky senza codice boilerplate:
// bun run sdk_example.ts (oppure deno run --allow-net --allow-env sdk_example.ts)
// npm install @proxyhat/node-sdk (o equivalente)
// Verifica la documentazione ufficiale per il pacchetto esatto
const PROXYHAT_GATE = "gate.proxyhat.com";
const PROXYHAT_PORT = 8080;
function buildProxyUrl(opts: {
country?: string;
session?: string;
socks?: boolean;
}): string {
const proto = opts.socks ? "socks5" : "http";
const port = opts.socks ? 1080 : 8080;
let username = "user";
if (opts.country) username += `-country-${opts.country}`;
if (opts.session) username += `-session-${opts.session}`;
return `${proto}://${username}:pass@${PROXYHAT_GATE}:${port}`;
}
// Esempio: crea 10 proxy URLs con geo-targeting e sessioni univoche
const proxies = Array.from({ length: 10 }, (_, i) =>
buildProxyUrl({ country: "US", session: `batch-${Date.now()}-${i}` })
);
console.log("Proxy generati:", proxies.length);
console.log("Esempio:", proxies[0]);
Per il proxy fetch JavaScript in scenari production, l'approccio SDK riduce la complessità ma ti vincola al ecosistema Node. Se vuoi sfruttare feature native di Deno come caCerts o la performance di Bun per richieste ad alta concorrenza, la configurazione manuale resta preferibile.
Considerazioni etiche e legali
Usare proxy non è una scusa per ignorare i limiti legali. Alcuni principi fondamentali:
- Usa API ufficiali quando disponibili. Se un sito offre un'API pubblica o a pagamento, è quasi sempre più affidabile e legale dello scraping.
- Rispetta
robots.txte i Terms of Service. Anche se non sempre legalmente vincolanti, indicano l'intento del proprietario del sito. - Negli Stati Uniti, il Computer Fraud and Abuse Act (CFAA) può applicarsi all'accesso non autorizzato a sistemi protetti. Lo scraping di dati pubblici è generalmente permesso, ma l'aggiramento di misure di autenticazione o di controllo accessi può violare la legge.
- Nell'UE, il GDPR regola la raccolta e il trattamento di dati personali. Se scraped dati che contengono informazioni personali, devi avere una base giuridica legittima.
- Rate limiting responsabile. Anche con proxy residenziali, imposta ritardi ragionevoli (es. 1-2 richieste al secondo per sito) per non sovraccaricare i server target.
Per approfondire i casi d'uso legittimi, consulta le nostre guide su web scraping e SERP tracking.
Configurazione ProxyHat: riepilogo pratico
Ecco un riepilogo dei parametri di connessione ProxyHat che abbiamo usato in tutti gli esempi:
- Gateway HTTP:
http://USERNAME:PASSWORD@gate.proxyhat.com:8080 - Gateway SOCKS5:
socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080 - Geo-targeting:
user-country-USouser-country-DE-city-berlin - Sessioni sticky:
user-session-abc123 - Combinazione:
user-country-US-session-abc123
Consulta la nostra pagina prezzi per i piani disponibili e la lista completa delle locazioni proxy per il geo-targeting.
Key Takeaways
fetch()nativa non supporta proxy: Deno usaDeno.createHttpClient({ proxy })passato come{ client }, Bun usafetch(url, { proxy })direttamente.- Geo-targeting e sessioni sticky si codificano nel username:
user-country-US-session-abc123.- SOCKS5 è disponibile sulla porta
1080; HTTP sulla porta8080.- Le variabili
HTTP_PROXY/HTTPS_PROXYsono utili per configurazioni globali, ma la configurazione per-client è preferibile per rotazione e geo-targeting dinamico.- In produzione: usa retry con backoff esponenziale, timeout con
AbortController, e chiudi sempre i client Deno conclient.close().- I proxy residenziali sono essenziali per target ad alta resistenza (SERP, e-commerce, social media).
- Rispetta sempre robots.txt, ToS, CFAA e GDPR. Usa le API ufficiali quando disponibili.
FAQ
Come si usa un proxy in Deno e Bun?
In Deno si crea un client HTTP personalizzato con Deno.createHttpClient({ proxy: { url: "http://user:pass@gate.proxyhat.com:8080" } }) e lo si passa a fetch(url, { client }). In Bun si usa direttamente fetch(url, { proxy: "http://user:pass@gate.proxyhat.com:8080" }). Entrambi supportano SOCKS5 sulla porta 1080 e geo-targeting codificato nel username.
Perché fetch() non usa i proxy automaticamente?
La specifica WHATWG Fetch non include un concetto nativo di proxy HTTP. I browser delegano il routing alle impostazioni di sistema. I runtime server-side come Deno e Bun hanno dovuto costruire soluzioni proprie: Deno tramite createHttpClient e Bun tramite l'opzione proxy in fetch(). Le variabili d'ambiente HTTP_PROXY e HTTPS_PROXY offrono un fallback globale.
Quale tipo di proxy è migliore per Deno e Bun?
Dipende dal caso d'uso. I proxy residenziali sono ideali per target ad alta resistenza (SERP, e-commerce, social media) perché usano IP di ISP reali. I proxy datacenter sono più economici e veloci, adatti per API pubbliche e dati non protetti. I proxy mobile offrono la massima affidabilità per app che rilevano il tipo di rete. ProxyHat supporta tutti e tre i tipi.
Come evitare blocchi quando si usano proxy in Deno e Bun?
Usa sessioni sticky per mantenere lo stesso IP durante flussi multi-pagina, ruota IP tra richieste indipendenti, imposta timeout con AbortController (es. 10-15 secondi), implementa retry con backoff esponenziale su errori 429 e 5xx, e mantieni un rate limit responsabile (1-2 richieste al secondo per sito). I proxy residenziali con geo-targeting riducono drasticamente i blocchi rispetto ai proxy datacenter.
Posso usare il ProxyHat Node SDK con Deno o Bun?
Sì, il ProxyHat SDK è compatibile con entrambi i runtime grazie alla loro compatibilità con le API Node. Tuttavia, se hai bisogno di feature native specifiche come caCerts in Deno o la configurazione one-line di Bun, la configurazione manuale del proxy offre maggiore controllo e flessibilità.






