---
title: "cURL in JavaScript: fetch, Axios und Proxy"
description: "Das JavaScript-Gegenstück zu cURL sind fetch und Axios. Header, Body, Authentifizierung und Proxy-Einrichtung in Node.js mit getesteten Codebeispielen."
url: https://proxynet.io/de/blog/curl-in-javascript
date: 2026-09-13
author: "Acar Diveroli"
category: "Anleitungen"
lang: de
---

# cURL in JavaScript: fetch, Axios und Proxy

API-Dokumentationen und die Entwicklertools des Browsers geben Beispielanfragen oft als **cURL-Befehl** an. Für einen schnellen Test im Terminal ist das ideal; müssen Sie dieselbe Anfrage aber in eine Node.js-Anwendung oder ein Scraping-Skript übertragen, müssen Sie den Befehl in JavaScript übersetzen. In diesem Beitrag erklären wir die JavaScript-Entsprechungen der meistgenutzten cURL-Optionen, zeigen Übersetzungsbeispiele, vier Wege für die Proxy-Nutzung in Node.js, die Fehlerbehandlung und häufige Fehler.

Alle Beispiele wurden mit Node.js 24, undici 8 und Axios 1.20 getestet.

> **Hinweis: Kurz gesagt**
>
> Das Gegenstück zu `curl URL` ist `fetch(url)` bzw. `axios.get(url)`; `-H`-Header werden zum `headers`-Objekt, der `-d`-Body zu `body`/dem zweiten Parameter, und `-x proxy` wird in Node.js zum undici-`ProxyAgent` bzw. für Axios zum `https-proxy-agent`. Im Browser laufendes JavaScript kann einen Proxy nicht per Code definieren.

## Was ist das Gegenstück zu cURL in JavaScript?

Es gibt zwei Hauptoptionen:

- **fetch:** Ist in Browsern und seit Node.js 18 nativ eingebaut. Kein zusätzliches Paket nötig. Node.js' fetch-Implementierung nutzt im Hintergrund die Bibliothek [undici](https://undici.nodejs.org/).
- **Axios:** Eine seit Langem verwendete, populäre Bibliothek, die JSON automatisch umwandelt und Interceptor-Unterstützung für Anfragen und Antworten bietet.

Es ist auch möglich, ohne das Terminal zu verlassen, einen cURL-Befehl direkt weiterzuverwenden (mit `child_process`), doch dieser Weg erschwert Fehlerbehandlung und Portabilität; Sie bleiben davon abhängig, dass cURL auf der Maschine installiert ist. Mit einem nativen Client zu schreiben ist fast immer die bessere Wahl.

## JavaScript-Entsprechungen der cURL-Optionen

| cURL | fetch | Axios |
|---|---|---|
| `curl URL` | `fetch(url)` | `axios.get(url)` |
| `-X POST` | `method: "POST"` | `axios.post(url, daten)` |
| `-H "Name: Wert"` | `headers: { Name: "Wert" }` | `headers: { Name: "Wert" }` |
| `-d '{"a":1}'` | `body: JSON.stringify({ a: 1 })` | Objekt als zweiter Parameter |
| `-d "a=1&b=2"` | `body: new URLSearchParams({ a: 1, b: 2 })` | `new URLSearchParams(...)` als zweiter Parameter |
| `-F "datei=@a.png"` | `body: FormData` | `FormData` als zweiter Parameter |
| `-u benutzer:passwort` | `Authorization: "Basic ..."`-Header | `auth: { username, password }` |
| `-b "name=wert"` (Cookie) | `headers: { Cookie: "name=wert" }` | `headers: { Cookie: "name=wert" }` |
| `-A "UA"` | `headers: { "User-Agent": "UA" }` | `headers: { "User-Agent": "UA" }` |
| `-L` (Weiterleitung folgen) | Folgt standardmäßig | Folgt standardmäßig |
| `-x proxy` | `dispatcher: new ProxyAgent(...)` | `httpsAgent` oder `proxy` |
| `-m 20` (Timeout) | `signal: AbortSignal.timeout(20000)` | `timeout: 20000` |
| `-i` (Antwort-Header) | `response.headers` | `response.headers` |
| `-o datei` | Body mit `fs.writeFile` schreiben | `responseType: "stream"` |

## Beispiel: eine POST-Anfrage übersetzen

Betrachten wir folgenden cURL-Befehl:

```bash
curl -X POST https://httpbin.org/post \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -d '{"q": 1}'
```

### Mit fetch

```javascript
const response = await fetch("https://httpbin.org/post", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer TOKEN",
  },
  body: JSON.stringify({ q: 1 }),
  signal: AbortSignal.timeout(20000),
});

if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data.json);
```

fetch hat eine Besonderheit: Gibt der Server 404 oder 500 zurück, wird **keine** Exception geworfen. Ob die Antwort erfolgreich war, müssen Sie selbst über `response.ok` prüfen. Ein Netzwerkfehler (DNS, Verbindungsabbruch, Timeout) kommt hingegen als Exception.

### Mit Axios

```bash
npm install axios
```

```javascript
import axios from "axios";

const { data } = await axios.post(
  "https://httpbin.org/post",
  { q: 1 },
  { headers: { Authorization: "Bearer TOKEN" }, timeout: 20000 },
);

console.log(data.json);
```

Axios wandelt das Objekt selbst in JSON um, fügt den `Content-Type`-Header hinzu und wirft bei Antworten außerhalb des 2xx-Bereichs eine Exception.

## Beispiel: Formularübertragung und Datei-Upload

Eine Formularübertragung im Format `-d "a=1&b=2"` wird in JavaScript mit `URLSearchParams` abgebildet:

```javascript
const response = await fetch("https://httpbin.org/post", {
  method: "POST",
  body: new URLSearchParams({ a: "1", b: "2" }),
});
console.log((await response.json()).form);
```

Wird ein `URLSearchParams`-Body übergeben, setzt fetch den `Content-Type`-Header selbst auf `application/x-www-form-urlencoded`. Für Datei-Uploads (`-F`) wird `FormData` verwendet, auch hier wird die Boundary automatisch eingefügt. Ein Detail: Beziehen Sie die `fetch`-Funktion aus dem undici-Paket, nehmen Sie auch die `FormData`-Klasse aus demselben Paket; die eingebaute `FormData` passt nicht zu undicis `fetch`, und der Body wird dann als reiner Text übertragen.

```javascript
import { openAsBlob } from "node:fs";

const form = new FormData();
form.append("datei", await openAsBlob("./a.png"), "a.png");

const response = await fetch("https://httpbin.org/post", { method: "POST", body: form });
console.log(Object.keys((await response.json()).files));
```

## Vier Wege, in Node.js einen Proxy zu nutzen

Bei cURL ist der Proxy eine einzelne Option `-x`. In Node.js hängt die Methode davon ab, welchen Client Sie verwenden.

### 1. fetch und undici ProxyAgent

```bash
npm install undici
```

```javascript
import { fetch, ProxyAgent } from "undici";

const dispatcher = new ProxyAgent("http://benutzer:passwort@pr.proxynet.io:8000");

const response = await fetch("https://httpbin.org/ip", { dispatcher });
console.log(await response.text());
```

Beachten Sie, dass wir auch die `fetch`-Funktion aus dem undici-Paket importieren. Node.js' eingebautes fetch basiert ebenfalls auf undici, doch da im separat installierten Paket ein Versionsunterschied bestehen kann, ist es am sichersten, beide aus demselben Paket zu beziehen.

### 2. Globale Einstellung für alle fetch-Aufrufe

Soll jeder fetch-Aufruf der Anwendung denselben Proxy verwenden, können Sie einen globalen Dispatcher definieren:

```javascript
import { ProxyAgent, setGlobalDispatcher } from "undici";

setGlobalDispatcher(new ProxyAgent("http://benutzer:passwort@pr.proxynet.io:8000"));

const response = await fetch("https://httpbin.org/ip");
console.log(await response.text());
```

Diese Methode erfasst auch fetch-Aufrufe, die aus einer Bibliothek eines Drittanbieters heraus erfolgen; ohne den Quellcode der Bibliothek anzurühren, leiten Sie deren Traffic über den Proxy.

### 3. Über eine Umgebungsvariable, ohne Codeänderung

Aktuelle Node.js-Versionen können bei aktivierter Variable `NODE_USE_ENV_PROXY` für das eingebaute fetch die üblichen Proxy-Umgebungsvariablen lesen:

```bash
NODE_USE_ENV_PROXY=1 HTTPS_PROXY="http://benutzer:passwort@pr.proxynet.io:8000" node anwendung.mjs
```

Diese Methode ist nützlich, um ein bestehendes Skript ohne Quellcode-Änderung über einen Proxy zu leiten. Auch die Variable `NO_PROXY` wird gelesen; interne Netzwerkadressen können Sie dieser Liste hinzufügen, um sie vom Proxy auszunehmen. Ob die Funktion in Ihrer Version verfügbar ist, prüfen Sie in der [Node.js-Dokumentation](https://nodejs.org/api/cli.html).

### 4. Axios und HTTPS-Ziele

Die eingebaute `proxy`-Option von Axios funktioniert für unverschlüsselte HTTP-Adressen problemlos:

```javascript
const { data } = await axios.get("http://httpbin.org/ip", {
  proxy: {
    protocol: "http",
    host: "pr.proxynet.io",
    port: 8000,
    auth: { username: "benutzer", password: "passwort" },
  },
});
```

Bei HTTPS-Adressen ist ein Proxy-Agent verlässlicher:

```bash
npm install https-proxy-agent
```

```javascript
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";

const httpsAgent = new HttpsProxyAgent("http://benutzer:passwort@pr.proxynet.io:8000");

const { data } = await axios.get("https://httpbin.org/ip", { httpsAgent, proxy: false });
console.log(data);
```

Die Zeile `proxy: false` ist wichtig; sie schaltet Axios' eigene Proxy-Logik ab und überlässt den Tunnel vollständig dem Agenten. Erstellen Sie den Agenten einmal und binden ihn mit `axios.create({ httpsAgent, proxy: false })` an eine Instanz, müssen Sie ihn nicht bei jedem Aufruf erneut schreiben.

> **Tipp**
>
> Auch wenn die Proxy-Adresse mit `http://` beginnt, können Sie sicher HTTPS-Websites ansteuern. Über den Proxy wird per HTTP ein Tunnel aufgebaut, und der HTTPS-Traffic der Website wird innerhalb dieses Tunnels verschlüsselt übertragen. Die Details der Unterschiede finden Sie in unserem Beitrag [SOCKS und HTTP Proxy im Vergleich](/de/blog/socks-vs-http-proxy).

## Die vier Methoden im Vergleich

| Methode | Umfang | Codeänderung | Geeignet für |
|---|---|---|---|
| undici `ProxyAgent` | Einzelner Aufruf | `dispatcher` bei jedem Aufruf | Unterschiedlicher Proxy pro Anfrage |
| `setGlobalDispatcher` | Alle fetch-Aufrufe | Eine Zeile beim Start | Ein Proxy für die gesamte Anwendung |
| `NODE_USE_ENV_PROXY` | Alle eingebauten fetch-Aufrufe | Keine | Bestehendes Skript, Deployment-Umgebung |
| Axios + Agent | Axios-Instanz | `httpsAgent` + `proxy: false` | Wenn Axios im Projekt genutzt wird |

## Wiederholung und Nebenläufigkeit

In einem echten Scraping-Skript scheitern Anfragen gelegentlich; der Proxy erreicht das Ziel nicht, oder die Website liefert 429. Die folgende Hilfsfunktion wiederholt eine fehlgeschlagene Anfrage mit exponentiellem Backoff und begrenzt die Anzahl gleichzeitig offener Anfragen:

```javascript
import { fetch, ProxyAgent } from "undici";

const dispatcher = new ProxyAgent("http://benutzer:passwort@pr.proxynet.io:8000");

async function getir(url, deneme = 3) {
  for (let i = 0; i < deneme; i++) {
    try {
      const r = await fetch(url, { dispatcher, signal: AbortSignal.timeout(20000) });
      if (r.status === 429 || r.status >= 500) throw new Error(`HTTP ${r.status}`);
      return await r.text();
    } catch (hata) {
      if (i === deneme - 1) throw hata;
      await new Promise((coz) => setTimeout(coz, 1000 * 2 ** i));
    }
  }
}

async function topluGetir(urls, esZamanli = 5) {
  const sonuclar = [];
  for (let i = 0; i < urls.length; i += esZamanli) {
    const grup = urls.slice(i, i + esZamanli);
    sonuclar.push(...(await Promise.allSettled(grup.map(getir))));
  }
  return sonuclar;
}

const urls = Array.from({ length: 20 }, (_, i) => `https://httpbin.org/get?i=${i}`);
const sonuclar = await topluGetir(urls);
console.log(sonuclar.filter((s) => s.status === "fulfilled").length, "erfolgreich");
```

`Promise.allSettled` verhindert, dass der Fehler einer einzelnen Anfrage die ganze Gruppe zu Fall bringt; Sie können jedes Ergebnis einzeln prüfen. Die Wartezeit verdoppelt sich bei jedem Versuch; in konstanten Abständen zu beharren verschärft eine Website mit Rate-Limiting nur weiter.

## Häufige Fehler

### Sonderzeichen im Passwort

Enthält Ihr Proxy-Passwort Zeichen wie `@`, `:` oder `/`, kodieren Sie diese innerhalb der Adresse mit `encodeURIComponent`. Andernfalls wird die Adresse falsch geparst und Sie erhalten den Fehler "407 Proxy Authentication Required".

### Anfragen ohne Timeout

In Standardeinstellungen kann eine Anfrage lange auf eine Antwort warten und Ihr Skript bleibt hängen. Setzen Sie bei fetch mit `AbortSignal.timeout`, bei Axios mit `timeout` für jede Anfrage eine Zeitgrenze.

### Zu viele gleichzeitige Anfragen

Mit `Promise.all` Hunderte Anfragen auf einmal zu starten, überfordert sowohl Ihre eigenen Verbindungsgrenzen als auch führt es dazu, dass Sie auf der Zielseite ins Rate-Limiting geraten. Begrenzen Sie die Nebenläufigkeit wie oben gezeigt in kleinen Gruppen. Bei Aufgaben mit vielen Anfragen senkt [Rotierender Proxy](https://proxynet.io/de/rotating-proxy) das Risiko einer Sperrung, indem der Traffic auf verschiedene IPs verteilt wird.

### `agent` an das eingebaute fetch übergeben

In Node.js' alter `http.request`-API wird der Proxy über die Option `agent` übergeben. Das eingebaute fetch kennt diese Option nicht und ignoriert sie stillschweigend; die Anfrage geht dann ohne Proxy hinaus. Der richtige Schlüssel für fetch ist `dispatcher`.

### Browser-Header unverändert kopieren

Aus den Entwicklertools kopierte Anfragen tragen browserspezifische Header wie `sec-ch-ua`, `sec-fetch-*`. In Node.js müssen diese nicht gesendet werden, und manche können auf der Zielseite als Inkonsistenz gewertet werden; lassen Sie nur wirklich benötigte Header übrig.

### Seiten, für die eine HTTP-Anfrage nicht ausreicht

fetch und Axios beziehen nur das vom Server zurückgegebene HTML. Wird der Inhalt im Browser nachträglich per JavaScript geladen, finden Sie auf der Seite nicht, wonach Sie suchen. In diesem Fall müssen Sie entweder die Hintergrund-API-Anfrage finden oder eine Browser-Automatisierung nutzen. Die Optionen haben wir in [Web Scraping: JavaScript oder Python?](/de/blog/web-scraping-javascript-vs-python) verglichen; die Proxy-Nutzung mit Puppeteer zeigen wir in [Puppeteer und CAPTCHA](/de/blog/puppeteer-captcha).

## fetch oder Axios?

- Wählen Sie **fetch**: wenn Sie keine zusätzliche Abhängigkeit wollen, der Code sowohl im Browser als auch in Node.js laufen soll, oder Sie von undicis Verbindungsmanagement profitieren möchten.
- Wählen Sie **Axios**: wenn Sie Annehmlichkeiten wie automatische JSON-Umwandlung, Interceptor oder Exceptions bei Antworten außerhalb des 2xx-Bereichs brauchen, oder es im Projekt bereits genutzt wird.

Der Unterschied zwischen beiden ist eher Gewohnheit als Funktionalität. In einem neuen Projekt mit fetch zu beginnen hält die Anzahl der Abhängigkeiten niedrig; in einem großen Axios-Projekt gibt es keinen Grund, zu fetch zu wechseln.

## Häufig gestellte Fragen

### Kann ich einen cURL-Befehl automatisch in JavaScript übersetzen?

In den Entwicklertools des Browsers können Sie im Netzwerk-Tab eine Anfrage per Rechtsklick mit "Copy as fetch" direkt als fetch-Code kopieren. Prüfen Sie den entstandenen Code trotzdem; browserspezifische Header können in Node.js überflüssig sein. Wenn Sie denselben Befehl nach Python übertragen, finden Sie die Entsprechungen der cURL-Optionen in `json=`, `data=` und `params=` als Tabelle in unserem Artikel [JSON mit Python Requests per POST senden: cURL-Äquivalente](/de/blog/python-requests-post-json).

### Kann ich in Node.js einen SOCKS5-Proxy nutzen?

Das eingebaute fetch und der undici-ProxyAgent sind für HTTP-Proxys gedacht. Für SOCKS5 müssen Sie mit einem zusätzlichen Paket wie `socks-proxy-agent` einen Agenten definieren. Bei cURL wird das Schema `socks5h://` dagegen direkt unterstützt; Details in unserem Beitrag [Wie nutzt man einen Proxy mit cURL?](/de/blog/curl-proxy).

### Kann im Browser laufendes JavaScript einen Proxy definieren?

Nein. Das fetch im Browser erlaubt es nicht, die Proxy-Einstellung über Code zu ändern; der Proxy wird in den Einstellungen des Browsers oder des Betriebssystems definiert. Proxy-Verwaltung aus dem Code heraus ist Serverumgebungen wie Node.js vorbehalten. Für Proxy auf Browserebene werden Erweiterungen wie [SwitchyOmega](/de/blog/switchy-omega) genutzt.

### Wie behalte ich Cookies zwischen Anfragen bei?

Das eingebaute fetch speichert keine Cookies. Sie müssen den `Set-Cookie`-Header aus der Antwort lesen und ihn der nächsten Anfrage als `Cookie`-Header hinzufügen, oder mit Axios ein auf `tough-cookie` basierendes Cookie-Jar verwenden. Denken Sie daran, dass bei angemeldeten Abläufen auch die IP konstant bleiben muss; [Sticky-Proxy](https://proxynet.io/de/sticky-proxy) ist genau dafür konzipiert.

### Kann ich bei jeder Anfrage einen anderen Proxy nutzen?

Ja. Mit undici können Sie jedem Aufruf einen anderen `ProxyAgent` geben. Statt die Liste selbst zu verwalten, ist es jedoch einfacher, einen Rotating-Proxy zu nutzen: eine Adresse, bei jeder Verbindung eine andere ausgehende IP.

### Funktioniert derselbe Code auch in TypeScript?

Ja. undici und Axios liefern Typdefinitionen mit; für die `dispatcher`-Option müssen Sie undicis eigenen `fetch`-Typ verwenden, da die Typdefinition des eingebauten fetch diese Option nicht kennt.

## Fazit

cURL-Befehle lassen sich in JavaScript eins zu eins mit fetch oder Axios abbilden. Für Proxys in Node.js gibt es vier Wege: den undici-ProxyAgent, einen globalen Dispatcher, die Umgebungsvariable `NODE_USE_ENV_PROXY` und für Axios einen Proxy-Agenten. Timeout, Fehlerprüfung, Wiederholung mit exponentiellem Backoff und eine von Anfang an eingebaute Nebenläufigkeitsgrenze machen Ihre Skripte deutlich zuverlässiger. Passende Pakete für Web-Traffic finden Sie auf unserer Seite [HTTPS-Proxy](https://proxynet.io/de/https-proxy).
