WeProxy

Leitfaden

Proxy in Node.js nutzen: Beispiele für axios, undici und fetch

12 Min. Lesezeit

In Node.js wird ein Proxy für das eingebaute fetch mit NODE_USE_ENV_PROXY, in undici mit ProxyAgent und in axios über die Einstellung proxy festgelegt. Dazu HTTP- und SOCKS5-Beispiele, die Verwaltung von Sticky-Sessions, die Prüfung der Ausgangs-IP und Proxy-Fehler je nach Client.

Das Wichtigste in Kürze

  • Node.js liest die Proxy-Einstellung nicht von selbst; das eingebaute fetch nutzt HTTP_PROXY, HTTPS_PROXY und NO_PROXY erst, wenn Node mit NODE_USE_ENV_PROXY=1 oder --use-env-proxy gestartet wird (ab Node.js 24 und 22.21).
  • In undici wird der Proxy der Anfrage als dispatcher: new ProxyAgent("http://USER:PASSWORD@host:port") übergeben; auch die Funktion fetch sollte aus demselben undici-Paket importiert werden, sonst kann ein Versionsunterschied die Anfrage scheitern lassen.
  • axios nimmt den Proxy über die Einstellung proxy: { protocol, host, port, auth } entgegen; im Objekt auth steht das Passwort unkodiert. Bei https-proxy-agent wird proxy: false ergänzt, damit es keinen Konflikt mit Umgebungsvariablen gibt.
  • Für SOCKS5 nutzen Sie in axios und node:https das Paket socks-proxy-agent, in undici die experimentelle Klasse Socks5ProxyAgent; das Schema socks5h überlässt die DNS-Auflösung dem Proxy.
  • undici legt die eigentliche Fehlerursache in err.cause ab; bei 407 wiederholen Sie die Anfrage nicht, sondern prüfen, ob das Passwort mit encodeURIComponent kodiert und das Paket aktiv ist.

In Node.js gibt es drei gängige Wege, einen Proxy zu nutzen: Für das eingebaute fetch starten Sie Node mit NODE_USE_ENV_PROXY=1 und setzen die Variable HTTPS_PROXY, im Paket undici übergeben Sie der Anfrage die Klasse ProxyAgent als dispatcher, und in axios verwenden Sie die Einstellung proxy. Die Proxy-Adresse hat in jedem Fall das Format http://USER:PASSWORD@host:port; für SOCKS5 brauchen Sie socks-proxy-agent oder die undici-Klasse Socks5ProxyAgent.

Welcher Weg passt, hängt von Ihrem HTTP-Client ab. Node.js liest die Proxy-Einstellung für http.request und fetch nicht von selbst: Entweder schalten Sie die Unterstützung für Umgebungsvariablen ein, oder Sie machen jedem Client den Proxy einzeln bekannt. Die Beispiele verwenden die WeProxy-Gateway-Adresse gw.weproxy.com.tr:8989; USER und PASSWORD sind Ihre Zugangsdaten aus dem Kundenpanel.

Wie schreibt man eine Proxy-Adresse in Node.js?

Alle Clients erwarten den Proxy im selben URL-Format:

schema://benutzer:passwort@host:port

Das Schema beschreibt das Protokoll des Proxy-Servers. Auch wenn die Zielseite HTTPS nutzt, beginnt die Adresse eines HTTP-Proxys mit http://; der Client schickt ein CONNECT an den Proxy, und die TLS-Verbindung wird innerhalb dieses Tunnels aufgebaut. Schreiben Sie die Adresse mit https://, versucht der Client, mit dem Proxy selbst TLS zu sprechen. undici meldet in diesem Fall den Fehler ERR_SSL_WRONG_VERSION_NUMBER. Den Unterschied zwischen HTTP-Proxy und SOCKS5 erklärt der Artikel HTTP vs. SOCKS5.

Enthält das Passwort @, :, / oder #, kodieren Sie es vor dem Einsetzen in die URL mit encodeURIComponent. Ein nicht kodiertes @ bringt das Parsen der Adresse durcheinander, und undici wirft TypeError: Invalid URL:

const user = encodeURIComponent(process.env.WEPROXY_USERNAME);
const pass = encodeURIComponent(process.env.WEPROXY_PASSWORD);
export const PROXY = `http://${user}:${pass}@gw.weproxy.com.tr:8989`;

Bewahren Sie die Zugangsdaten in einer Umgebungsvariable oder einem Secret-Manager auf; dann landet das Passwort nicht in Git, wenn der Code dorthin wandert. Haben Sie im Panel eine Liste im Format ip:port:user:pass erhalten, wandelt der Proxy-Format-Konverter die Zeilen ins URL-Format um. Details zu IPv6-Adressen und socks5h stehen im Leitfaden zu Proxy-Formaten.

Wie nutzt man einen Proxy mit dem eingebauten fetch von Node.js?

Ab Node.js 24 und ab 22.21 kann das eingebaute fetch die Variablen HTTP_PROXY, HTTPS_PROXY und NO_PROXY lesen. Dieses Verhalten ist standardmäßig ausgeschaltet und wird mit der Variable NODE_USE_ENV_PROXY=1 oder dem Flag --use-env-proxy aktiviert. Fehlt das Flag, ignoriert Node die Variablen, und die Anfrage geht direkt über Ihre eigene IP hinaus.

export HTTPS_PROXY="http://USER:[email protected]:8989"
export HTTP_PROXY="$HTTPS_PROXY"
export NO_PROXY="localhost,127.0.0.1"
NODE_USE_ENV_PROXY=1 node app.mjs

In PowerShell sieht dieselbe Einstellung so aus:

$env:HTTPS_PROXY = "http://USER:[email protected]:8989"
$env:HTTP_PROXY = $env:HTTPS_PROXY
node --use-env-proxy app.mjs

In der Datei app.mjs steht keine einzige Zeile zum Proxy:

const res = await fetch('https://api.ipify.org?format=json', {
  signal: AbortSignal.timeout(30_000),
});
console.log(await res.json()); // { ip: '<Proxy-Ausgangs-IP>' }

In aktuellen Versionen leitet das Flag auch die globalen Agents der Module node:http und node:https über den Proxy; ältere Aufrufe wie https.get laufen damit ohne Codeänderung über den Proxy. Details stehen in der Node.js-CLI-Dokumentation. Die Methode eignet sich, um eine bestehende Anwendung über einen Proxy zu schicken, ohne ihren Code anzufassen. Der gesamte Prozess nutzt dabei einen einzigen Proxy; brauchen Sie pro Anfrage einen anderen, nehmen Sie die nächste Methode.

Wie nutzt man einen Proxy mit undici ProxyAgent?

undici ist der HTTP-Client unter der fetch-Implementierung von Node.js und erscheint auf npm auch als eigenes Paket. Mit der Klasse ProxyAgent legen Sie den Proxy auf Anfrage-Ebene fest:

npm install undici
import { ProxyAgent, fetch } from 'undici';
import { PROXY } from './proxy.mjs';

const dispatcher = new ProxyAgent(PROXY);

const res = await fetch('https://api.ipify.org?format=json', {
  dispatcher,
  signal: AbortSignal.timeout(30_000),
});
console.log(await res.json());

await dispatcher.close();

Importieren Sie auch die Funktion fetch aus demselben Paket wie ProxyAgent. Die in Node gebündelte undici-Version kann hinter der Version auf npm zurückliegen. Übergeben Sie dem eingebauten fetch von Node.js 24 ein ProxyAgent-Objekt aus undici 8 von npm, scheitert die Anfrage mit fetch failed, und als eigentliche Ursache steht dort invalid onRequestStart method.

Wenn Sie das Passwort nicht in die URL schreiben möchten, können Sie die Zugangsdaten als Header-Wert übergeben. In dieser Form ist keine Prozentkodierung nötig:

const basic = Buffer.from(
  `${process.env.WEPROXY_USERNAME}:${process.env.WEPROXY_PASSWORD}`
).toString('base64');

const dispatcher = new ProxyAgent({
  uri: 'http://gw.weproxy.com.tr:8989',
  token: `Basic ${basic}`,
});

Um alle fetch-Aufrufe der Anwendung über den Proxy zu leiten, nutzen Sie setGlobalDispatcher(new ProxyAgent(PROXY)). Es gibt auch eine Variante, die Umgebungsvariablen liest, aber kein Prozess-Flag braucht: EnvHttpProxyAgent liest HTTPS_PROXY und NO_PROXY selbst. Die vollständige Liste der Optionen finden Sie in der undici-Dokumentation zu ProxyAgent.

Wie nutzt man einen Proxy mit axios?

axios nimmt den Proxy in Node.js über die Einstellung proxy entgegen. Weil die Zugangsdaten in eigenen Feldern stehen, müssen Sie Sonderzeichen nicht kodieren:

import axios from 'axios';

const client = axios.create({
  proxy: {
    protocol: 'http',
    host: 'gw.weproxy.com.tr',
    port: 8989,
    auth: {
      username: process.env.WEPROXY_USERNAME,
      password: process.env.WEPROXY_PASSWORD,
    },
  },
  timeout: 30_000,
});

const { data } = await client.get('https://api.ipify.org?format=json');
console.log(data);

Aktuelle axios-Versionen öffnen für HTTPS-Ziele einen CONNECT-Tunnel zum Proxy. In Version 1.16.1 wurde ein Fehler behoben, durch den der Inhalt einer HTTPS-Anfrage in manchen Konfigurationen unverschlüsselt an einen HTTP-Proxy gehen konnte (axios-Changelog). Arbeiten Sie mit einer älteren Version, aktualisieren Sie axios oder überlassen Sie den Tunnel dem Paket https-proxy-agent:

import axios from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { PROXY } from './proxy.mjs';

const client = axios.create({
  httpsAgent: new HttpsProxyAgent(PROXY),
  proxy: false,
});

axios liest standardmäßig die Variablen HTTPS_PROXY und NO_PROXY; ohne die Zeile proxy: false kann der Proxy aus der Umgebung mit Ihrem Agent kollidieren. Einen HTTPS_PROXY-Wert mit prozentkodiertem Passwort schickt axios dagegen in kodierter Form an den Proxy, und das Ergebnis ist 407. Enthält das Passwort Sonderzeichen, verwenden Sie in axios das Objekt auth.

Wie nutzt man einen SOCKS5-Proxy in Node.js?

Weder das eingebaute fetch noch axios sprechen SOCKS5 von sich aus. Für axios und node:https gibt es das Paket socks-proxy-agent:

npm install socks-proxy-agent
import axios from 'axios';
import { SocksProxyAgent } from 'socks-proxy-agent';

const user = encodeURIComponent(process.env.WEPROXY_USERNAME);
const pass = encodeURIComponent(process.env.WEPROXY_PASSWORD);
const agent = new SocksProxyAgent(`socks5h://${user}:${pass}@gw.weproxy.com.tr:8989`);

const client = axios.create({ httpAgent: agent, httpsAgent: agent, proxy: false });
console.log((await client.get('https://api.ipify.org')).data);

Das Schema socks5h überlässt die Namensauflösung dem Proxy; mit socks5 wird der Domainname des Ziels über Ihren eigenen DNS-Server aufgelöst. Wenn Sie undici nutzen, erledigt die Klasse Socks5ProxyAgent dieselbe Aufgabe und lässt den Domainnamen immer auf der Proxy-Seite auflösen. Die Klasse ist noch als experimentell markiert und gibt bei der ersten Verwendung eine ExperimentalWarning aus:

import { Socks5ProxyAgent, fetch } from 'undici';

const dispatcher = new Socks5ProxyAgent(`socks5://${user}:${pass}@gw.weproxy.com.tr:8989`);
const res = await fetch('https://api.ipify.org', { dispatcher });
console.log(await res.text());

Die SOCKS5-Unterstützung hängt vom Paket ab. Rotating Residential IPv4 bietet HTTP und SOCKS5; der Mobile 5G Proxy mit echter SIM funktioniert nur mit HTTP. UDP-Verkehr wie Gaming oder VoIP transportieren diese Clients nicht; Setups mit UDP-Bedarf beschreibt der UDP-Proxy-Leitfaden.

axios, undici und fetch im Vergleich: Was passt wann?

MerkmalEingebautes fetchundiciaxios
InstallationKeine (Node.js 18+)npm install undicinpm install axios
Wie wird der Proxy übergebenNODE_USE_ENV_PROXY=1 + HTTPS_PROXYdispatcher: new ProxyAgent(...)proxy: {...} oder httpsAgent
Anderer Proxy pro AnfrageNein, prozessweitJaJa
ZugangsdatenIn der URLIn der URL oder tokenObjekt auth
SOCKS5NeinSocks5ProxyAgent (experimentell)socks-proxy-agent
UmgebungsvariablenNur mit FlagMit EnvHttpProxyAgentStandardmäßig an
Geeignet fürProxy ohne CodeänderungNeuer Code, mehrere Proxys, hohe ParallelitätBestehende axios-Projekte

In einem neuen Projekt bringt undici mit einem einzigen Paket Proxy pro Anfrage, SOCKS5 und die Einstellungen für den Verbindungspool mit. Baut die Codebasis auf axios auf, müssen Sie den Client nicht wechseln; die Einstellung proxy oder https-proxy-agent genügt.

Wie verwaltet man rotierende und Sticky-IPs in Node.js?

Bei einem rotierenden Gateway bleibt die Proxy-Adresse gleich, und die Ausgangs-IP wechselt aus dem Pool. Auf der Node.js-Seite müssen Sie auf die Wiederverwendung von Verbindungen achten. undici ProxyAgent nutzt den Tunnel, den es zu einem Ziel geöffnet hat, für die folgenden Anfragen weiter; seit Node.js 19 ist keepAlive bei den globalen Agents von http und https standardmäßig aktiv. Greift der IP-Wechsel erst bei einer neuen Verbindung, können aufeinanderfolgende Anfragen über denselben Agent dieselbe IP haben. Ob das Gateway pro Anfrage oder pro Verbindung rotiert, sehen Sie, wenn Sie api.ipify.org zweimal mit demselben Agent und danach zweimal mit zwei getrennten Agents abfragen.

Aufgaben wie Login, Warenkorb oder mehrstufige Formulare brauchen dagegen dieselbe IP über alle Anfragen hinweg. In den Residential- und Mobile-Pools von WeProxy wird dafür eine Session-ID an den Benutzernamen angehängt. Format des Benutzernamens und Session-Dauer hängen vom Produkt ab, übernehmen Sie beides deshalb aus dem Panel. Im Code reicht es, für jedes Konto einen eigenen Agent zu öffnen:

import { ProxyAgent, fetch } from 'undici';

// Benutzernamen aus dem Panel kopieren; jedes Profil hat seine eigene Session-ID.
const PROFILES = {
  'konto-1': 'USER_WITH_SESSION_1',
  'konto-2': 'USER_WITH_SESSION_2',
};
const pass = encodeURIComponent(process.env.WEPROXY_PASSWORD);

const agents = Object.fromEntries(
  Object.entries(PROFILES).map(([name, user]) => [
    name,
    new ProxyAgent(`http://${encodeURIComponent(user)}:${pass}@gw.weproxy.com.tr:8989`),
  ])
);

for (const [name, dispatcher] of Object.entries(agents)) {
  const res = await fetch('https://api.ipify.org', { dispatcher });
  console.log(name, await res.text());
}

Zwei Profile dürfen sich keine Session-ID teilen, sonst sieht die Zielseite zwei verschiedene Nutzer mit derselben IP. Welche Aufgabe Sticky und welche Rotation braucht, zeigt der Leitfaden zu Sticky vs. Rotating mit einer Szenario-Tabelle. Das Paket, das beide Session-Arten anbietet, finden Sie auf der Seite Rotating Residential Proxy.

Wenn Sie viele URLs abarbeiten, starten Sie nicht alle gleichzeitig mit Promise.all, sondern begrenzen Sie die Parallelität. Ein kleiner Pool ohne zusätzliches Paket:

async function runPool(items, limit, worker) {
  const results = [];
  let next = 0;
  const lanes = Array.from({ length: limit }, async () => {
    while (next < items.length) {
      const i = next++;
      results[i] = await worker(items[i]).catch((err) => err);
    }
  });
  await Promise.all(lanes);
  return results;
}

const urls = Array(20).fill('https://api.ipify.org');
const ips = await runPool(urls, 5, async (url) =>
  (await fetch(url, { dispatcher: agents['konto-1'] })).text()
);

Die Grenze setzt hier die Zielseite: Ein plötzlicher Schwall von Anfragen über dieselbe IP läuft in ihr Rate Limit und bekommt 429 zurück.

Wie prüft man, ob der Proxy funktioniert?

Der schnellste Test: Fragen Sie die Ausgangs-IP einmal ohne und einmal mit Proxy ab und vergleichen Sie beide Werte:

import { ProxyAgent, fetch as undiciFetch } from 'undici';
import { PROXY } from './proxy.mjs';

const dispatcher = new ProxyAgent(PROXY);
const direct = await (await fetch('https://api.ipify.org')).text();
const viaProxy = await (await undiciFetch('https://api.ipify.org', { dispatcher })).text();

console.log({ direct, viaProxy });
if (direct === viaProxy) throw new Error('Anfrage geht nicht über den Proxy');

Sind beide Werte gleich, kommt die Proxy-Einstellung nicht bei der Anfrage an. Prüfen Sie beim eingebauten fetch das Flag NODE_USE_ENV_PROXY, bei axios mit proxy: false den Konflikt mit Umgebungsvariablen und in jedem Fall die Liste NO_PROXY. Land und Netz der Proxy-IP zeigt das My-IP-Tool. Um den Proxy unabhängig vom Code zu testen, nutzen Sie den Proxy-Checker; funktioniert ein Proxy dort, aber nicht in Node, liegt das Problem in der Client-Konfiguration. Wenn Sie denselben Test lieber im Terminal machen, helfen die Befehle aus dem Artikel Proxy mit cURL nutzen.

Welche Proxy-Fehler treten in Node.js auf und wie behebt man sie?

Dasselbe Problem zeigt sich in jedem Client als anderer Fehler. Die Zuordnungen in der Tabelle stammen aus einem lokalen Test-Proxy mit Node.js 24, undici 8, axios 1.21 und https-proxy-agent 9:

Situationundici fetchaxiosnode:https + HttpsProxyAgent
Zugangsdaten abgelehnt (407)fetch failed; Ursache „Proxy response (407) !== 200 when HTTP Tunneling“AxiosError, status: 407Kein Fehler, statusCode der Antwort ist 407
Keine Verbindung zum Proxyfetch failed; Ursache ECONNREFUSEDECONNREFUSEDEvent error, ECONNREFUSED
ZeitüberschreitungTimeoutError mit AbortSignal.timeoutECONNABORTEDWird mit req.setTimeout abgefangen
Proxy-Adresse mit https:// geschriebenERR_SSL_WRONG_VERSION_NUMBEREPROTO („wrong version number“)EPROTO („wrong version number“)
Passwort nicht kodiertTypeError: Invalid URLMit dem Objekt auth kein ProblemTypeError: Invalid URL

undici legt die eigentliche Ursache des Fehlers in err.cause ab; geben Sie nur err.message aus, sieht jeder Fehler wie „fetch failed“ aus. Schreiben Sie deshalb auch err.cause?.code und err.cause?.message ins Log.

Bei 407 prüfen Sie zuerst, ob das Passwort kodiert ist, und dann, ob das Paket aktiv ist. Arbeiten Sie mit IP-Whitelist, muss die Ausgangs-IP des Servers, auf dem der Code läuft, im Panel eingetragen sein. Beginnt 407 erst, nachdem ein lokal laufendes Skript auf einen Server umgezogen ist, liegt es daran. Welche Methode für welches Produkt gilt, steht im Leitfaden zur Proxy-Authentifizierung. Wiederholen Sie Anfragen nach einem 407 nicht; mit denselben Zugangsdaten ändert sich das Ergebnis nicht.

429, 502, 503 und 504 können vorübergehend sein und verlangen erneute Versuche mit wachsendem Abstand. Auf welcher Ebene jeder Code entsteht, erklärt der Leitfaden zu Proxy-Fehlercodes. Läuft die Verbindung ständig in einen Timeout, sperrt Ihr Firmennetz oder Ihr Cloud-Anbieter möglicherweise ausgehende Verbindungen zu Port 8989. Bei einem Zertifikatsfehler schalten Sie die Prüfung nicht mit NODE_TLS_REJECT_UNAUTHORIZED=0 ab; diese Einstellung deaktiviert die TLS-Prüfung für den gesamten Prozess.

Compliance und Sicherheit bei der Proxy-Nutzung mit Node.js

Wenn Sie ein Skript schreiben, das Daten sammelt, halten Sie sich an die robots.txt des Ziels (RFC 9309) und seine Nutzungsbedingungen, auch wenn die Anfragen über einen Proxy laufen, und halten Sie die Anfragerate auf einem Niveau, das die Seite verkraftet. Verarbeiten Sie personenbezogene Daten, gelten die Pflichten aus DSGVO und KVKK unabhängig von der Proxy-Nutzung. Welche Nutzungen bei WeProxy erlaubt sind und welche nicht, steht auf der Seite zur akzeptablen Nutzung.

Weil die Proxy-URL das Passwort enthält, taucht es leicht in Fehlermeldungen und Logs auf. Zerlegen Sie die Adresse vor dem Loggen mit new URL(PROXY) und löschen Sie das Feld password. Die Setup-Schritte stehen auf der Seite zur Node.js-Integration, ein lauffähiges Beispielprojekt im Repository weproxy-io/nodejs-proxy. Für Browser-Automatisierung sehen Sie sich die Puppeteer-Integration an, für dieselben Aufgaben in Python den Artikel Proxy in Python nutzen. Wie Sie IP-Typ und Session für Scraping-Aufgaben wählen, beschreibt die Seite zu Web Scraping.

Häufige Fragen

Wie nutzt man einen Proxy mit fetch in Node.js?

Ab Node.js 24 und 22.21 setzen Sie die Variable HTTPS_PROXY auf http://USER:PASSWORD@host:port und starten die Anwendung mit NODE_USE_ENV_PROXY=1 oder node --use-env-proxy; danach laufen die Anfragen des eingebauten fetch über den Proxy. Brauchen Sie pro Anfrage einen anderen Proxy, installieren Sie das Paket undici von npm, übergeben ein ProxyAgent-Objekt mit der Option dispatcher und importieren auch fetch aus undici.

Warum nutzt Node.js trotz HTTPS_PROXY meine echte IP?

Node.js liest den Proxy aus Umgebungsvariablen standardmäßig nicht. Für das eingebaute fetch und node:https brauchen Sie NODE_USE_ENV_PROXY=1 oder --use-env-proxy; ältere Versionen bieten diese Unterstützung nicht. Möglicherweise deckt auch die Liste NO_PROXY den Domainnamen des Ziels ab. Fragen Sie api.ipify.org einmal mit und einmal ohne Proxy ab und vergleichen Sie die Ergebnisse, dann finden Sie das Problem schnell.

Wie richtet man in axios einen Proxy mit Benutzername und Passwort ein?

Geben Sie in axios.create der Einstellung proxy die Felder protocol: "http", host, port und auth: { username, password } mit. Im Objekt auth steht das Passwort unverändert, eine Prozentkodierung ist nicht nötig. Bei älteren axios-Versionen ist es für HTTPS-Anfragen sicherer, das Paket https-proxy-agent als httpsAgent zu übergeben und proxy: false zu ergänzen; zudem empfiehlt es sich, axios aktuell zu halten.

Wie nutzt man einen SOCKS5-Proxy in Node.js?

Das eingebaute fetch und axios unterstützen SOCKS5 nicht von sich aus. Für axios oder node:https installieren Sie das Paket socks-proxy-agent, erstellen mit der Adresse socks5h://USER:PASSWORD@host:port einen Agent und übergeben ihn an die Felder httpAgent und httpsAgent. Mit undici erledigt die experimentelle Klasse Socks5ProxyAgent dieselbe Aufgabe. Die SOCKS5-Unterstützung hängt vom Paket ab; der Mobile 5G Proxy funktioniert nur mit HTTP.

Warum meldet undici nur „fetch failed“?

undici fetch wirft Netzwerkfehler als allgemeinen TypeError und legt die eigentliche Ursache im Feld err.cause ab. Bei 407 steht am Ende der Kette etwa die Meldung „Proxy response (407) !== 200 when HTTP Tunneling“, ist der Proxy nicht erreichbar, der Code ECONNREFUSED. Schreiben Sie auch err.cause?.code und err.cause?.message ins Log, unterscheiden Sie danach den Fehlertyp und wiederholen Sie nur bei vorübergehenden Fehlern.

Jetzt Starten

Testen Sie noch heute Ihr Proxy-Setup

Überprüfen Sie die Konnektivität mit kostenlosen Tools oder sprechen Sie mit dem Vertrieb, um das richtige Paket auszuwählen.