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

Kompletny przewodnik po konfiguracji proxy w nowoczesnych środowiskach JavaScript — Deno i Bun. Przykłady kodu, geo-targeting, sesje sticky, SOCKS5 i wskazówki produkcyjne.

Using Proxies in Deno and Bun: A Code-First Guide for Modern JavaScript

Dlaczego natywny fetch() ignoruje proxy w Deno i Bun

Standard fetch() zdefiniowany przez WHATWG Fetch API nie zawiera żadnego mechanizmu konfiguracji proxy. To celowa decyzja projektowa — specyfikacja opisuje wyłącznie warstwę HTTP, a routing sieciowy pozostawia środowisku uruchomieniowemu. Przez to fetch() w przeglądarce, Node.js, Deno i Bun zachowuje się inaczej niż starsze biblioteki takie jak request czy axios, które automatycznie czytały zmienne środowiskowe HTTP_PROXY/HTTPS_PROXY.

Dla programistów JavaScript używających proxy w Deno i Bun oznacza to konieczność jawnego przekazania konfiguracji proxy do klienta HTTP. Każde środowisko rozwiązuje to inaczej: Deno wymaga utworzenia dedykowanego klienta przez Deno.createHttpClient, a Bun rozszerza sygnaturę fetch() o opcję proxy. W tym artykule pokażemy konfigurację krok po kroku, z kodem produkcyjnym i przykładami dla ProxyHat.

Kontekst techniczny: jak Deno i Bun rozwiązują problem proxy

Deno: Deno.createHttpClient({ proxy })

Deno udostępnia API Deno.createHttpClient, które tworzy konfigurowalny klient HTTP. Obiekt klienta przekazuje się do fetch() jako opcję client. Proxy konfiguruje się przez właściwość proxy z polami url i opcjonalnie basicAuth.

// deno run --allow-net --unstable-net proxy_fetch.ts

const proxyUrl = "http://gate.proxyhat.com:8080";
const username = "user-country-US-session-abc123";
const password = "twoje_haslo";

const client = Deno.createHttpClient({
  proxy: {
    url: proxyUrl,
    basicAuth: { username, password },
  },
});

try {
  const res = await fetch("https://httpbin.org/ip", { client });
  const data = await res.json();
  console.log("IP przez proxy:", data.origin);
} catch (err) {
  console.error("Błąd żądania:", err.message);
} finally {
  client.close();
}

Ważne: Deno.createHttpClient wymaga flagi --unstable-net w starszych wersjach Deno (przed 2.2). Od Deno 2.2+ API jest stabilne. Klient należy zamykać przez client.close(), aby uniknąć wycieków zasobów przy dużej liczbie żądań.

Bun: fetch(url, { proxy })

Bun przyjmuje bardziej bezpośrednie podejście — opcja proxy jest wbudowana w standardową sygnaturę fetch(). Nie trzeba tworzyć osobnego obiektu klienta.

// bun run proxy_fetch.ts

const proxyUrl = "http://user-country-US-session-abc123:twoje_haslo@gate.proxyhat.com:8080";

try {
  const res = await fetch("https://httpbin.org/ip", {
    proxy: proxyUrl,
  });
  const data = await res.json();
  console.log("IP przez proxy:", data.origin);
} catch (err) {
  console.error("Błąd żądania:", err.message);
}

Bun parsuje URL proxy zgodnie z RFC 7617 (HTTP Basic Authentication), więc poświadczenia mogą być osadzone bezpośrednio w adresie. To najkrótsza droga do działania proxy w JavaScript — jedna linijka.

Kodowanie geo-targetingu i sesji sticky w nazwie użytkownika

ProxyHat, podobnie jak większość zaawansowanych dostawców proxy, pozwala na przekazywanie flag geo i sesji w nazwie użytkownika. To eliminuje potrzebę osobnych endpointów dla każdego kraju czy miasta.

FlagaPrzykład nazwy użytkownikaOpis
Krajuser-country-DEIP z Niemiec
Kraj + miastouser-country-DE-city-berlinIP z Berlina
Sticky sessionuser-session-abc123Ten sam IP dla wielu żądań
Kraj + sesjauser-country-US-session-abc123Stały IP z USA

Przykład w Deno z geo-targetingiem i sticky session:

// Geo-targeting + sticky session w Deno

function createProxyClient(country: string, session: string) {
  const username = `user-country-${country}-session-${session}`;
  return Deno.createHttpClient({
    proxy: {
      url: "http://gate.proxyhat.com:8080",
      basicAuth: { username, password: "twoje_haslo" },
    },
  });
}

const deClient = createProxyClient("DE", "sess-001");
const usClient = createProxyClient("US", "sess-002");

const [deRes, usRes] = await Promise.all([
  fetch("https://httpbin.org/ip", { client: deClient }),
  fetch("https://httpbin.org/ip", { client: usClient }),
]);

console.log("DE IP:", (await deRes.json()).origin);
console.log("US IP:", (await usRes.json()).origin);

deClient.close();
usClient.close();

SOCKS5 na porcie 1080

Gdy HTTP CONNECT nie wystarcza — np. w środowiskach z restrykcyjnymi firewallami lub gdy potrzebujesz pełnego tunelowania TCP — ProxyHat udostępnia SOCKS5 na porcie 1080.

// Bun — SOCKS5 proxy

const socksUrl = "socks5://user-country-DE-session-abc123:twoje_haslo@gate.proxyhat.com:1080";

const res = await fetch("https://httpbin.org/ip", {
  proxy: socksUrl,
});
console.log(await res.json());

W Deno obsługa SOCKS5 przez Deno.createHttpClient zależy od wersji — w starszych kompilacjach konieczne może być użycie zewnętrznej biblioteki takiej jak socks z npm. Bun natywnie obsługuje SOCKS5 w opcji proxy od wersji 1.1+.

Zmienne środowiskowe HTTP_PROXY/HTTPS_PROXY

Zarówno Deno, jak i Bun automatycznie czytają zmienne środowiskowe HTTP_PROXY i HTTPS_PROXY (zgodnie z konwencją z dokumentacją MDN o nagłówkach HTTP). To wygodne w środowiskach CI/CD i kontenerach Docker.

# Ustawienie zmiennej środowiskowej
export HTTP_PROXY="http://user-country-US:twoje_haslo@gate.proxyhat.com:8080"
export HTTPS_PROXY="http://user-country-US:twoje_haslo@gate.proxyhat.com:8080"

# Deno automatycznie użyje proxy
deno run --allow-net --allow-env script.ts

# Bun również automatycznie użyje proxy
bun run script.ts

Kiedy używać zmiennych środowiskowych vs konfiguracji per-klient?

  • Zmienne środowiskowe — gdy wszystkie żądania mają przechodzić przez ten sam proxy (np. całe środowisko w firmowym VPN lub kontenerze).
  • Konfiguracja per-klient — gdy potrzebujesz różnych proxy dla różnych żądań, np. rotacja krajów, osobne sesje sticky, lub mieszanie proxy residential z datacenter.

Proxy residential dla celów z wysokim ryzykiem blokady

Serwery datacenter są łatwo wykrywane przez zaawansowane systemy anti-bot (Cloudflare, Akamai, Datadome). Adresy IP z bloków AWS, DigitalOcean czy Hetzner są oznaczane jako hosting w bazach takich jak MaxMind, co często skutkuje CAPTCHA lub HTTP 403. Proxy residential używa adresów przydzielonych prawdziwym dostawcom ISP, co sprawia, że ruch wygląda jak organiczny.

Poniżej przykład rotacji puli sesji sticky z wykorzystaniem Promise.all i AbortController jako timeout — w Bun, ale wzorzec działa identycznie w Deno:

// Bun — rotacja sesji sticky z timeoutem i obsługą błędów

const PROXY_GATEWAY = "gate.proxyhat.com:8080";
const PASSWORD = "twoje_haslo";
const TARGET_URL = "https://api.example.com/data";
const TIMEOUT_MS = 10_000;

interface ScrapeResult {
  session: string;
  status: number;
  body: unknown;
}

async function fetchWithSession(sessionId: string): Promise<ScrapeResult> {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);

  const proxyUrl = `http://user-country-US-session-${sessionId}:${PASSWORD}@${PROXY_GATEWAY}`;

  try {
    const res = await fetch(TARGET_URL, {
      proxy: proxyUrl,
      signal: controller.signal,
      headers: {
        "Accept": "application/json",
        "User-Agent": "MyApp/1.0",
      },
    });

    return {
      session: sessionId,
      status: res.status,
      body: await res.json(),
    };
  } catch (err) {
    if (err instanceof DOMException && err.name === "AbortError") {
      console.warn(`Sesja ${sessionId}: timeout po ${TIMEOUT_MS}ms`);
    } else {
      console.error(`Sesja ${sessionId}:`, err.message);
    }
    return { session: sessionId, status: 0, body: null };
  } finally {
    clearTimeout(timeout);
  }
}

// Uruchom 10 równoległych żądań z różnymi sesjami sticky
const sessions = Array.from({ length: 10 }, (_, i) => `sess-${i.toString().padStart(3, "0")}`);
const results = await Promise.all(sessions.map(fetchWithSession));

const successCount = results.filter((r) => r.status === 200).length;
console.log(`Sukces: ${successCount}/${results.length} (${(successCount / results.length * 100).toFixed(1)}%)`);

Ten wzorzec daje pełną kontrolę nad współbieżnością, timeoutami i identyfikacją sesji. Przy 10 równoległych żądaniach z timeoutem 10 s, całkowity czas wykonania rzadko przekracza 12 s nawet przy jednym retried request.

Wskazówki produkcyjne: retry, backoff, własne CA i ponowne użycie połączeń

Retry z wykładniczym backoffem

// Deno — retry z backoffem i ponownym użyciem klienta

const MAX_RETRIES = 3;
const BASE_DELAY_MS = 500;

async function fetchWithRetry(
  url: string,
  client: Deno.HttpClient,
  retries = MAX_RETRIES,
): Promise<Response> {
  for (let attempt = 0; attempt <= retries; attempt++) {
    try {
      const res = await fetch(url, { client });
      if (res.status === 429 || res.status >= 500) {
        throw new Error(`HTTP ${res.status}`);
      }
      return res;
    } catch (err) {
      if (attempt === retries) throw err;
      const delay = BASE_DELAY_MS * Math.pow(2, attempt);
      console.warn(`Próba ${attempt + 1}/${retries + 1} nieudana, retry za ${delay}ms`);
      await new Promise((r) => setTimeout(r, delay));
    }
  }
  throw new Error("Nieosiągalne");
}

// Użycie — klient jest tworzony raz i ponownie używany
const client = Deno.createHttpClient({
  proxy: {
    url: "http://gate.proxyhat.com:8080",
    basicAuth: { username: "user-country-PL", password: "twoje_haslo" },
  },
});

try {
  const res = await fetchWithRetry("https://api.example.com/data", client);
  console.log(await res.json());
} finally {
  client.close();
}

Własne CA w Deno (caCerts)

Jeśli Twoje proxy używa certyfikatu TLS z wewnętrznego CA (np. w środowisku korporacyjnym), Deno pozwala na dostarczenie własnych certyfikatów przez opcję caCerts:

// Deno — własne CA

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

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

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

Porównanie: natywne API vs ProxyHat SDK

ProxyHat udostępnia SDK dla Node.js, które działa również pod Deno i Bun dzięki kompatybilności npm. Poniżej porównanie podejścia natywnego i SDK:

CechaNatywne API (Deno/Bun)ProxyHat SDK
Konfiguracja proxyRęczne budowanie URL/obiektuAutomatyczne z konfiguracją
Rotacja IPWłasna logika sesjiWbudowana rotacja
Retry/backoffRęczna implementacjaWbudowane z konfiguracją
Geo-targetingPrzez nazwę użytkownikaPrzez API SDK
ZależnościBrak (natywne API)Jeden pakiet npm
WydajnośćMaksymalna (zero narzutów)Niewielki narzut
// ProxyHat SDK — działa w Deno i Bun przez npm
// npm install @proxyhat/sdk

import { ProxyHat } from "@proxyhat/sdk";

const ph = new ProxyHat({
  username: "user",
  password: "twoje_haslo",
  gateway: "gate.proxyhat.com",
  port: 8080,
  defaultCountry: "US",
});

// Automatyczna rotacja i retry
const result = await ph.fetch("https://api.example.com/data", {
  country: "DE",
  session: "my-session",
  retries: 3,
  timeout: 10_000,
});

console.log(await result.json());

SDK upraszcza konfigurację, ale natywne API daje pełną kontrolę i zero dodatkowych zależności — co jest szczególnie ważne w środowiskach serverless i edge, gdzie rozmiar bundla ma znaczenie.

Etyczny scraping: publiczne dane, CFAA i GDPR

Scraping danych publicznych jest legalny w wielu jurysdykcjach, ale granice zależą od kontekstu. W USA Computer Fraud and Abuse Act (CFAA) był podstawą procesów przeciwko scraperom, choć orzeczenie Van Buren v. United States (2021) zawęziło definicję „nieautoryzowanego dostępu”. W UE GDPR ogranicza zbieranie danych osobowych, a wyrok Trybunału Sprawiedliwości UE w sprawie C-302/20 (hiQ vs LinkedIn) potwierdził prawo do scrapowania publicznie dostępnych danych.

Najlepsze praktyki:

  • Zawsze sprawdzaj robots.txt i warunki usługi (ToS) przed rozpoczęciem scrapowania.
  • Używaj oficjalnego API, jeśli jest dostępne — jest szybsze, stabilniejsze i legalne.
  • Limituj częstotliwość żądań — 1–5 żądań/s na domenę to bezpieczny próg dla większości stron.
  • Nie zbieraj danych osobowych bez podstawy prawnej zgodnej z GDPR.
  • Identyfikuj swojego bota w nagłówku User-Agent z danymi kontaktowymi.

Sprawdź nasze przypadki użycia web scrapingu oraz śledzenie SERP, aby zobaczyć, jak proxy residential zwiększa niezawodność zbierania danych. Pełną listę dostępnych lokalizacji znajdziesz na stronie lokalizacje proxy, a ceny i plany na stronie cennika ProxyHat.

Najważniejsze wnioski

  • fetch() w Deno i Bun nie czyta proxy domyślnie — trzeba przekazać konfigurację jawnie.
  • Deno używa Deno.createHttpClient({ proxy }) + fetch(url, { client }).
  • Bun używa fetch(url, { proxy: 'http://...' }) w jednej linii.
  • Geo-targeting i sesje sticky koduje się w nazwie użytkownika: user-country-US-session-abc123.
  • SOCKS5 jest dostępny na porcie 1080 dla pełnego tunelowania TCP.
  • Proxy residential jest niezbędny dla celów z systemami anti-bot (Cloudflare, Datadome).
  • Produkcyjne wzorce: retry z backoffem, AbortController timeout, ponowne użycie klienta.
  • Zmienne HTTP_PROXY/HTTPS_PROXY są czytane automatycznie przez oba środowiska.

FAQ

Czym jest używanie proxy w Deno i Bun?

Używanie proxy w Deno i Bun polega na jawnym przekazaniu konfiguracji proxy do klienta HTTP, ponieważ standardowy fetch() nie obsługuje proxy domyślnie. W Deno tworzy się klienta przez Deno.createHttpClient({ proxy }), a w Bun przekazuje się opcję proxy bezpośrednio do fetch(). Proxy pozwala na ukrycie IP, geo-targeting i omijanie blokad anti-bot.

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

Te nowoczesne środowiska JavaScript nie obsługują proxy automatycznie, co oznacza, że programiści muszą wiedzieć, jak je skonfigurować. Bez poprawnej konfiguracji żądania wychodzą z IP serwera, co prowadzi do blokad, CAPTCHA i banów IP. Prawidłowa konfiguracja proxy residential w Deno i Bun pozwala na stabilny scraping, monitorowanie cen i zbieranie danych SERP.

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

Proxy residential jest najlepszy dla celów z systemami anti-bot, ponieważ używa IP od prawdziwych dostawców ISP. Proxy datacenter jest tańszy i szybszy, ale łatwo wykrywany. Proxy mobile jest najtrudniejszy do zablokowania, ale najdroższy. Dla większości zastosowań w Deno i Bun — scraping, SERP tracking, e-commerce — residential na porcie 8080 oferuje najlepszy stosunek ceny do niezawodności.

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

Używaj sesji sticky (user-session-abc123) dla żądań wymagających ciągłości IP, rotuj sesje dla równoległych żądań, ustawiaj realistyczny User-Agent, limituj częstotliwość do 1–5 żądań/s na domenę, implementuj retry z wykładniczym backoffem i używaj AbortController z timeoutem 10 s. Zawsze sprawdzaj robots.txt i warunki usługi przed scrapowaniem.

Gotowy, aby zacząć?

Dostęp do ponad 50 mln rezydencjalnych IP w ponad 148 krajach z filtrowaniem AI.

Zobacz cenyProxy rezydencjalne
← Powrót do Bloga