Używanie proxy w Deno i Bun: Przewodnik dla programistów

Kompletny przewodnik po konfiguracji proxy w nowoczesnych środowiskach JavaScript — Deno i Bun. Przykłady kodu, rotacja sesji, produkcja i etyka scrapingu.

Using Proxies in Deno and Bun: A Code-First Guide
W tym artykule

Dlaczego natywny fetch() ignoruje proxy w Deno i Bun

Używanie proxy w Deno i Bun zaczyna się od jednej niewygodnej prawdy: natywna funkcja fetch() w obu tych środowiskach nie honoruje proxy automatycznie. W przeciwieństwie do curl czy axios z biblioteką https-proxy-agent, standardowy fetch oparty na WHATWG Fetch API nie posiada parametru proxy w swojej specyfikacji. To oznacza, że nawet jeśli ustawisz HTTP_PROXY, Deno i Bun mogą go zignorować w zależności od wersji i konfiguracji.

Problem wynika z faktu, że Fetch API zdefiniowane przez WHATWG opisuje wyłącznie warstwę HTTP — proxy to kwestia transportu, która pozostaje poza zakresem specyfikacji. Każde środowisko musi samo zdecydować, jak — i czy w ogóle — mapować zmienne środowiskowe lub parametry klienta na warstwę połączenia TCP.

Deno rozwiązuje to poprzez Deno.createHttpClient(), który zwraca obiekt klienta HTTP z obsługą proxy, certyfikatów CA i timeoutów. Bun idzie dalej: dodaje opcję proxy bezpośrednio do fetch(), co czyni konfigurację jednoliniową. W obu przypadkach używamy gate.proxyhat.com jako bramy ProxyHat, z portem 8080 dla HTTP i 1080 dla SOCKS5.

Konfiguracja proxy w Deno — Deno.createHttpClient

Deno wymaga utworzenia klienta HTTP z konfiguracją proxy, a następnie przekazania go jako opcji client do fetch(). Oto minimalny, działający przykład:

// Deno: podstawowe proxy HTTP
const client = Deno.createHttpClient({
  proxy: {
    url: "http://gate.proxyhat.com:8080",
    basicAuth: {
      username: "user-country-US",
      password: "TWOJE_HASLO",
    },
  },
});

const res = await fetch("https://httpbin.org/ip", { client });
const body = await res.text();
console.log(body);
// { "origin": "198.51.100.42" }

Zauważ, że geo-targeting i sesje kodujemy w nazwie użytkownika, używając formatu ProxyHat: user-country-US-session-abc123. To pozwala kontrolować lokalizację IP i trzymałość sesji bez dodatkowych nagłówków.

SOCKS5 w Deno na porcie 1080

Deno obsługuje SOCKS5 przez ten sam interfejs createHttpClient — wystarczy zmienić URL i port:

// Deno: SOCKS5 proxy
const socksClient = Deno.createHttpClient({
  proxy: {
    url: "socks5://gate.proxyhat.com:1080",
    basicAuth: {
      username: "user-country-DE-city-berlin",
      password: "TWOJE_HASLO",
    },
  },
});

const res = await fetch("https://httpbin.org/headers", { client: socksClient });
console.log(await res.json());

Konfiguracja proxy w Bun — fetch z opcją proxy

Bun upraszcza sprawę do jednej linii. Opcja proxy jest wbudowana w fetch():

// Bun: proxy w jednej linii
const res = await fetch("https://httpbin.org/ip", {
  proxy: "http://user-country-US:TWOJE_HASLO@gate.proxyhat.com:8080",
});
const data = await res.json();
console.log(data);

Dla SOCKS5 w Bun używamy portu 1080:

// Bun: SOCKS5 proxy
const res = await fetch("https://httpbin.org/ip", {
  proxy: "socks5://user-country-JP-session-s1:TWOJE_HASLO@gate.proxyhat.com:1080",
});
console.log(await res.json());

Zmienne środowiskowe HTTP_PROXY / HTTPS_PROXY

Zarówno Deno, jak i Bun mogą honorować zmienne środowiskowe HTTP_PROXY i HTTPS_PROXY, ale z ważnymi zastrzeżeniami:

  • Deno: automatycznie czyta HTTP_PROXY/HTTPS_PROXY tylko gdy nie podano jawnego klienta z proxy. Od wersji 1.40+ można wymusić env proxy bez createHttpClient.
  • Bun: czyta HTTP_PROXY i HTTPS_PROXY automatycznie, chyba że opcja proxy w fetch() nadpisze je.
# Ustawienie proxy przez env
export HTTP_PROXY="http://user-country-GB:TWOJE_HASLO@gate.proxyhat.com:8080"
export HTTPS_PROXY="http://user-country-GB:TWOJE_HASLO@gate.proxyhat.com:8080"

# Deno — env proxy działa domyślnie
deno run --allow-env --allow-net scraper.ts

# Bun — env proxy działa domyślnie
bun run scraper.ts

Kiedy używać env, a kiedy per-client? Env jest wygodne dla narzędzi CLI i prostych skryptów. Per-client jest lepsze, gdy potrzebujesz różnych proxy dla różnych zapytań (np. różne kraje), rotacji sesji w pętli, lub gdy chcesz uniknąć wycieku poświadczeń do zmiennych środowiskowych widocznych dla innych procesów.

Dlaczego proxy residential dla trudnych celów?

Proxy datacenter są łatwo wykrywane przez zaawansowane systemy anti-bot (Cloudflare, Datadome, PerimeterX), ponieważ ich zakresy IP należą do bloków ASN powiązanych z dostawcami chmury (AWS, Google Cloud, DigitalOcean). Według DataDome, ponad 60% ruchu bot na stronach e-commerce jest blokowanych już na poziomie TLS fingerprint i ASN.

Proxy residential używa adresów IP przypisanych do realnych dostawców ISP, co sprawia, że zapytania wyglądają jak organiczny ruch użytkownika. ProxyHat oferuje pulę residential IP w ponad 90 krajach — zobacz dostępne lokalizacje.

Rotacja sticky sessions z Promise.all i AbortController

Poniższy przykład pokazuje, jak równolele scrapować stronę używając puli sticky sessions, każda z timeoutem 10 sekund przez AbortController:

// Deno / Bun: rotacja sticky sessions
const SESSIONS = ["s1", "s2", "s3", "s4", "s5"];
const COUNTRIES = ["US", "GB", "DE", "FR", "JP"];
const PASSWORD = "TWOJE_HASLO";

async function fetchWithProxy(url, country, session, timeoutMs = 10000) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);

  const proxyUrl = `http://user-country-${country}-session-${session}:${PASSWORD}@gate.proxyhat.com:8080`;

  try {
    // W Bun:
    const res = await fetch(url, {
      proxy: proxyUrl,
      signal: controller.signal,
    });
    return await res.text();
  } finally {
    clearTimeout(timer);
  }
}

// Równoległe zapytania z 5 sesjami
const target = "https://example.com/api/data";
const results = await Promise.all(
  SESSIONS.map((s, i) =>
    fetchWithProxy(target, COUNTRIES[i], s).catch((e) =>
      console.error(`Session ${s} failed:`, e.message)
    )
  )
);

console.log(`Zakończono: ${results.filter(Boolean).length}/${SESSIONS.length} sukces`);

Ten wzorzec pozwala na 5 równoległych zapytań, każde z innym IP i krajem, z twardym timeoutem 10 000 ms. Jeśli jedno zapytanie zawiedzie, pozostałe kontynuują — Promise.all nie przerywa innych dzięki .catch() na poziomie mapowania.

Wskazówki produkcyjne

1. Retries z exponential backoff

async function fetchWithRetry(url, proxyUrl, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const controller = new AbortController();
      const timer = setTimeout(() => controller.abort(), 8000);
      const res = await fetch(url, {
        proxy: proxyUrl,
        signal: controller.signal,
      });
      clearTimeout(timer);

      if (res.status === 429 || res.status >= 500) {
        throw new Error(`HTTP ${res.status}`);
      }
      return await res.text();
    } catch (e) {
      const delay = Math.min(1000 * 2 ** attempt, 10000); // max 10s
      console.warn(`Próba ${attempt + 1} nieudana: ${e.message}, retry za ${delay}ms`);
      await new Promise((r) => setTimeout(r, delay));
    }
  }
  throw new Error(`Wszystkie próby wyczerpane dla ${url}`);
}

2. Niestandardowe CA w Deno

Jeśli scrapujesz przez firmowy MITM proxy lub potrzebujesz zaufać niestandardowemu CA, Deno pozwala podać certyfikaty w createHttpClient:

const caCert = await Deno.readTextFile("./custom-ca.pem");

const client = Deno.createHttpClient({
  proxy: {
    url: "http://gate.proxyhat.com:8080",
    basicAuth: { username: "user-country-US", password: "TWOJE_HASLO" },
  },
  caCerts: [caCert],
});

const res = await fetch("https://internal.corp.example.com", { client });
console.log(await res.text());

3. Reuse połączeń — connection pooling

Deno automatycznie reuses połączenia TCP w ramach tego samego klienta (Deno.createHttpClient). Nie twórz nowego klienta per zapytanie — utwórz go raz i przekazuj do fetch():

// Reuse klienta — wydajniej
const sharedClient = Deno.createHttpClient({
  proxy: {
    url: "http://gate.proxyhat.com:8080",
    basicAuth: { username: "user-country-US", password: "TWOJE_HASLO" },
  },
});

// Wielokrotne użycie tego samego klienta
const urls = [
  "https://httpbin.org/ip",
  "https://httpbin.org/headers",
  "https://httpbin.org/user-agent",
];

for (const url of urls) {
  const res = await fetch(url, { client: sharedClient });
  console.log(url, await res.json());
}

Porównanie: surowy fetch vs ProxyHat Node SDK

ProxyHat udostępnia Node SDK, który działa pod oboma środowiskami (Deno z kompatybilnością npm i Bun z natywnym wsparciem npm). Oto porównanie side-by-side:

Podejście Zalety Wady Środowisko
Surowy fetch z proxy (Bun) Zero zależności, jednoliniowa konfiguracja Brak wbudowanej rotacji, retry, logowania Bun
Deno.createHttpClient Pełna kontrola: CA, proxy, timeout Wymaga ręcznego zarządzania klientem Deno
ProxyHat Node SDK Rotacja, retry, logowanie out-of-the-box Dodatkowa zależność npm Deno + Bun
Env HTTP_PROXY Działa globalnie, proste dla CLI Brak per-request kontroli, wyciek poświadczeń Oba
// ProxyHat Node SDK — działa w Deno i Bun
import { ProxyHatClient } from "@proxyhat/node-sdk";

const ph = new ProxyHatClient({
  username: "user-country-US",
  password: "TWOJE_HASLO",
  gateway: "gate.proxyhat.com",
  port: 8080,
});

// SDK zarządza rotacją i retry automatycznie
const result = await ph.fetch("https://httpbin.org/ip", {
  country: "DE",
  session: "my-session-1",
  timeout: 8000,
  retries: 3,
});
console.log(await result.text());

SDK jest wygodne, gdy potrzebujesz rotacji sesji, retry z backoff i logowania bez pisania boilerplate. Surowy fetch jest lepszy, gdy zależy ci na minimalnym footprint i pełnej kontroli. Pełną dokumentację SDK znajdziesz na docs.proxyhat.com.

Etyka i legalność scrapingu

Scraping danych publicznych jest legalny w wielu jurysdykcjach, ale z ważnymi zastrzeżeniami:

  • USA: Computer Fraud and Abuse Act (CFAA) kryminalizuje „nieautoryzowany dostęp", ale orzeczenie Van Buren v. United States (2021) ograniczyło zakres. Scraping publicznych danych jest generalnie dozwolony, ale omijanie technicznych barier (CAPTCHA, rate limiting) może być problematyczne.
  • UE: RODO (GDPR) chroni dane osobowe. Scraping danych osobowych bez podstawy prawnej może naruszać GDPR, nawet jeśli dane są publicznie dostępne.
  • Najlepsza praktyka: najpierw sprawdź, czy cel ma oficjalne API. Jeśli tak — użyj go. Jeśli nie — przestrzegaj robots.txt, ogranicz częstotliwość zapytań (np. max 1 req/s) i scrapuj wyłącznie dane publiczne.

Proxy nie zwalnia z obowiązku przestrzegania prawa. Używaj ich odpowiedzialnie — do agregacji cen, monitorowania SERP, badań rynkowych i zbierania publicznych danych treningowych. Zobacz nasze przypadki użycia: web scraping i SERP tracking.

Kluczowe wnioski

Key Takeaways:

  • Deno wymaga Deno.createHttpClient({ proxy }) i przekazania { client } do fetch().
  • Bun obsługuje proxy jednoliniowo: fetch(url, { proxy: 'http://...' }).
  • Geo-targeting i sesje koduj w nazwie użytkownika: user-country-US-session-abc123.
  • SOCKS5 działa na porcie 1080, HTTP na 8080 — zawsze przez gate.proxyhat.com.
  • Używaj AbortController z timeoutem 8–10 s i retry z exponential backoff.
  • Reuse klientów HTTP w Deno — nie twórz nowego klienta per zapytanie.
  • ProxyHat Node SDK działa w obu środowiskach i oferuje rotację, retry i logowanie out-of-the-box.
  • Przestrzegaj CFAA, GDPR i robots.txt — proxy nie zwalnia z odpowiedzialności prawnej.

Gotowy, by zacząć? Sprawdź ceny ProxyHat i wybierz plan residential, który pasuje do Twojego obciążenia — od lekkich zadań SERP po pełne pipeline'y danych.

Często zadawane pytania

Czym jest używanie proxy w Deno i Bun?

Używanie proxy w Deno i Bun to konfiguracja natywnego fetch() do kierowania ruchu HTTP przez serwer proxy. W Deno wymaga to Deno.createHttpClient z opcją proxy, a w Bun wystarczy opcja proxy bezpośrednio w fetch(). Proxy pozwala na zmianę IP, geo-targeting i omijanie blokad rate-limit.

Dlaczego używanie proxy w Deno i Bun jest ważne dla użytkowników proxy?

Ponieważ natywny fetch() w obu środowiskach ignoruje proxy domyślnie — specyfikacja WHATWG Fetch API nie definiuje parametru proxy. Bez jawnej konfiguracji zapytania idą bezpośrednio z Twojego IP, co prowadzi do blokad przy scrapingu, monitoringu SERP i automatyzacji. Proxy residential dodatkowo omija detekcję ASN datacenter.

Który typ proxy działa najlepiej w Deno i Bun?

Proxy residential jest najlepszy dla trudnych celów z zaawansowanym anti-bot (Cloudflare, DataDome), ponieważ używa IP realnych ISP. Proxy datacenter jest szybsze i tańsze, ale łatwo wykrywalne. Dla Deno i Bun konfiguracja jest identyczna — różnica polega na jakości puli IP. ProxyHat oferuje residential w 90+ krajach z portem 8080 (HTTP) i 1080 (SOCKS5).

Jak uniknąć blokad używając proxy w Deno i Bun?

Używaj rotacji sticky sessions z różnymi krajami, ustawia timeout 8–10s przez AbortController, implementuj retry z exponential backoff (max 3 próby), ogranicz współbieżność do 5–10 równoległych zapytań i przestrzegaj robots.txt. Koduj geo-targeting w nazwie użytkownika (user-country-US-session-abc123) i używaj residential IP zamiast datacenter.

Czy ProxyHat Node SDK działa w Deno i Bun?

Tak, ProxyHat Node SDK jest kompatybilny z oboma środowiskami. Bun obsługuje pakiety npm natywnie, a Deno od wersji 2.0 ma pełną kompatybilność npm. SDK oferuje rotację sesji, retry z backoff i logowanie out-of-the-box, co eliminuje boilerplate. Alternatywnie można użyć surowego fetch z ręczną konfiguracją proxy.

Sprawdź konfigurację proxy w kilka sekund

Darmowy tester proxy — potwierdź, że Twoje IP są szybkie, anonimowe i nieblokowane.

Sprawdź proxy za darmo
← Powrót do Bloga