Vor ein paar Jahren hat mich ein Entwickler angerufen, dessen Skript „plötzlich nichts mehr konnte". Es hatte monatelang Daten von einer API geholt, und von einem Tag auf den anderen kam nur noch Fehler. Ich habe mir das Skript angesehen — es nutzte curl mit einem Dutzend Flags, die niemand im Team mehr erklären konnte, und vor allem: Es versteckte jede Fehlermeldung. Zehn Minuten später war die Ursache klar: Die API hatte die Basic-Auth-Anforderung geändert, und das Skript schickte seitdem einen kaputten Header. Ohne curl hätte ich das nie so schnell gefunden — und ohne die richtigen Flags wäre das Debuggen ein Ratespiel geblieben.

curl und wget sind die zwei Werkzeuge, die jeder Admin hundertmal am Tag benutzt und selten wirklich versteht. Dieser Artikel räumt auf: curl für APIs (mehr Kontrolle, mehr Optionen), wget für Downloads (Fortsetzen, Spiegeln), dazu die Flags, die ich täglich nutze, und ein Cheatsheet am Ende, das du dir ausdrucken kannst.

curl oder wget? Die Arbeitsteilung, die sich bewährt hat

Beide können HTTP, aber ihre Herzen schlagen unterschiedlich. curl (seit 1997, basierend auf der libcurl-Bibliothek) ist der Schweizer Taschenmesser für Requests: Du kontrollierst Methode, Header, Body, Zertifikate, Cookies, Timeouts — über 200 Optionen. Deshalb ist curl der Standard für API-Arbeit, in CI-Systemen und in jedem Skript, das mit einem Webserver redet. wget (GNU, seit 1996) ist der Download-Spezialist: Er kann Dateien fortsetzen (-c), ganze Websites spiegeln (--recursive), warten und wiederholen — Dinge, die curl nur umständlich kann.

Meine Faustregel: Antworten lesen → curl, Dateien holen → wget. Wenn du API-Endpunkte testest, ist curl die Wahl. Wenn du ein 4-GB-ISO oder eine Backup-Datei ziehst, ist wget mit -c der Freund, der nach einem Abbruch weitermacht, wo er aufgehört hat.

Das erste GET: Status, Header und der ganze Rest

Der simpelste API-Aufruf ist ein GET — aber die nackte Antwort sagt dir wenig, wenn du nicht weißt, ob sie vom Server oder vom Cache kommt. Deshalb sind diese drei Varianten der Anfang jeder curl-Karriere:

# Nur den HTTP-Status zeigen (perfekt für Monitoring)
curl -sS -o /dev/null -w "%{http_code}\n" https://api.example.com/v1/health

# Antwort-Header anzeigen (Cache, Server, CORS)
curl -sSI https://example.com

# Alles zeigen: Verbindungsaufbau, TLS, Request- und Response-Header
curl -v https://example.com

Das -w (write-out) ist mein heimlicher Favorit. Du kannst damit nicht nur den Status ausgeben, sondern auch Zeiten: %{time_total}, %{time_connect}, %{time_starttransfer}. Damit misst du in einer Zeile, ob eine API langsam ist, weil der Server trödelt oder weil die Leitung hakt — genau das, was man für die ersten 5 Minuten eines Performance-Problems braucht. Wenn du die Werte realistisch einordnen willst, hilft übrigens der bitcalc Downloadzeit-Rechner: Er rechnet aus, was eine gegebene Dateigröße über eine Leitung mit Overhead wirklich dauert — die gleiche Denkweise, nur für die andere Richtung.

Basic Auth: was -u wirklich tut

Viele APIs verlangen einen Benutzernamen und ein Passwort. curl macht das bequem:

curl -sS -u admin:meinPasswort https://api.example.com/v1/users

Was dabei passiert, ist vielen nicht klar: curl nimmt admin:meinPasswort, kodiert es Base64 und schickt es als Authorization: Basic YWRtaW46bWVpblBhc3N3b3J0 mit. Das ist keine Verschlüsselung — Base64 ist nur eine Kodierung, die jeder rückwärts lesen kann. Wenn du das selbst nachrechnen willst, nimm den bitcalc Base64-Encoder: Tippe admin:meinPasswort ein, und du siehst genau den String, der im Authorization-Header steht. Wer schon immer wissen wollte, was die API eigentlich erwartet, dem hilft das enorm beim Debuggen, wenn eine Auth nicht klappt.

Zwei Konsequenzen daraus:

  • Basic Auth nur über HTTPS. Über HTTP liest jeder im selben WLAN dein Passwort direkt aus dem Header mit — Base64 ist kein Schutz, sondern eine Transparenz.
  • Passwörter nicht in der Kommandozeile. ps aux zeigt dir jedes laufende Kommando inklusive Argumenten. Nutze curl --netrc mit einer Datei, die chmod 600 ist, oder lese die Credentials aus einer Umgebungsvariable: curl -u "$API_USER:$API_PASS". In CI-Systemen gehören Secrets in die Secret-Store, nie in den Command.

JSON-Antworten lesbar machen: die jq-Pipeline

Eine API-Antwort im Rohformat ist eine einzige, kilometerlange Zeile. Praktisch wird es erst mit jq — dem JSON-Parser fürs Terminal, den ich im JSON-Artikel schon ausführlich behandelt habe. Die Kombination ist simpel und mächtig:

# Antwort hübsch formatiert anzeigen
curl -sS https://api.example.com/v1/users | jq

# Nur die Namen extrahieren
curl -sS https://api.example.com/v1/users | jq '.users[].name'

# Zählen und Bedingungen
curl -sS https://api.example.com/v1/users | jq 'length'
curl -sS https://api.example.com/v1/users | jq '[.users[] | select(.active == true)] | length'

Wenn du keine jq-Installation hast oder eine Antwort schnell validieren willst, formatiert der bitcalc JSON-Formatter denselben Input im Browser — mit Baumansicht, Fehlerhinweisen und sauberer Einrückung. Ich nutze beides: jq im Terminal für Pipelines, den Formatter im Browser, wenn ich eine Antwort aus der API-Doku kopiert bekomme und erstmal verstehen will, was drinsteht.

POST, PUT, DELETE: die Methoden im Alltag

Daten senden ist der zweite große Anwendungsfall. Das wichtigste Detail dabei: -d setzt die Methode automatisch auf POST. Viele denken, sie bräuchten -X POST — meist reicht -d allein. -X wird nur dann wirklich gebraucht, wenn du eine Methode erzwingen willst, die curl sonst nicht wählen würde (etwa PUT oder DELETE mit leerem Body).

# JSON senden (Methode wird automatisch POST)
curl -sS -H "Content-Type: application/json" \
  -d '{"name":"neuer-server","role":"web"}' \
  https://api.example.com/v1/servers

# Explizit DELETE
curl -sS -X DELETE https://api.example.com/v1/servers/42

# Datei als Body senden
curl -sS -H "Content-Type: application/json" --data @payload.json \
  https://api.example.com/v1/import

Der --data @datei-Trick ist Gold wert: Statt eines riesigen JSON-Strings in der Kommandozeile (mit all den Quoting-Fallen) liest curl den Body aus einer Datei. Das macht Skripte wartbar und vermeidet die berüchtigten „ich sehe den Fehler nicht, weil das JSON im Command kaputt gequotet ist"-Sessions.

Downloads: wget -c und die Kunst des Fortsetzens

Jetzt der wget-Teil. Die wichtigste Option überhaupt ist -c (continue):

# Download fortsetzen nach Abbruch
wget -c https://example.com/backup-2026-10.iso

# Im Hintergrund mit Log
wget -b -o download.log https://example.com/backup-2026-10.iso

Während meiner Zeit als Dienstleister habe ich mehrfach Backup-Dateien von mehreren Gigabyte über unzuverlässige Leitungen gezogen. Ohne wget -c hieß jeder Abbruch: von vorn. Mit -c war ein 6-GB-Download nach dem dritten Abbruch einfach weiter — in Summe 40 Minuten statt dreimal 60. Die Datei am Ende war identisch, denn wget prüft die Länge und holt nur die fehlenden Bytes.

Wer den Download vorher planen will, rechnet mit dem bitcalc Downloadzeit-Rechner: Dateigröße und Leitung eintragen, Overhead und reale Durchsatz-Verluste einrechnen — und du weißt, ob der nächtliche Backup-Download in das Wartungsfenster passt oder nicht. Bei mir hat das schon zwei Mal verhindert, dass ich um 2 Uhr nachts vor einem halbfertigen Download stand.

Für curl-Downloads gilt übrigens: curl -sSLO speichert unter dem Server-Dateinamen, -o datei unter selbst gewähltem Namen. Und wenn du eine Datei mit begrenzter Geschwindigkeit ziehen willst, damit deine Kollegen noch surfen können: curl --limit-rate 200k oder wget --limit-rate=200k.

Fehlerbehandlung: damit Skripte nicht lügen

Der größte Fehler in curl-Skripten ist das stille Scheitern. curl ohne Flags gibt bei einem HTTP-404 trotzdem Exit-Code 0 zurück — dein Skript denkt „alles gut", obwohl die API „nicht gefunden" sagt. Drei Flags machen curl ehrlich:

# Exit-Code ungleich 0 bei HTTP-Fehlern (4xx/5xx)
curl -sS --fail https://api.example.com/v1/users

# Wiederholen mit Backoff
curl -sS --fail --retry 3 --retry-all-errors https://api.example.com/v1/users

# Timeout statt Ewigkeit
curl -sS --max-time 30 https://api.example.com/v1/users

Damit ist ein CI-Job, der eine API abfragt, ehrlich: schlägt die API fehl, schlägt der Job fehl — und die Logs sagen warum. --max-time ist der Rettungsanker für Cronjobs, die sonst an einem hängenden Server ewig laufen. Meine Standard-Kombination für jeden API-Check in Skripten lautet: curl -sS --fail --retry 3 --retry-all-errors --max-time 30. Das deckt 90 Prozent der Fälle ab, und die restlichen 10 Prozent sind genau die, die du dann wirklich sehen willst.

Zertifikate: -k ist ein Verbrechen

Ein Kapitel für sich: curl -k (und wget --no-check-certificate) überspringen die TLS-Zertifikatsprüfung. Das ist in 99 Prozent der Fälle die falsche Lösung — du schaltest genau den Schutz ab, der dich vor Man-in-the-Middle-Angriffen bewahrt. Wenn ein Zertifikat nicht passt, ist die richtige Antwort, das Problem zu lösen, nicht die Prüfung abzuschalten.

Die legitimen Alternativen:

  • Eigenes CA-Zertifikat: curl --cacert /pfad/zum/ca.pem — für interne Zertifikate deiner eigenen CA.
  • Host überprüfen: curl --resolve api.internal:443:192.168.10.5 — wenn der DNS-Name im Zertifikat nicht zur erreichbaren IP passt, aber das Zertifikat trotzdem stimmt.
  • Fingerprint prüfen: curl --pinnedpubkey sha256//... oder den Zertifikats-Fingerprint mit dem bitcalc Hash-Generator gegen die Angaben des Betreibers abgleichen.

Ich habe ein Kundenskript geerbt, das jahrelang mit -k lief, weil irgendwann jemand ein abgelaufenes Zertifikat hatte und keine Zeit zum Fixen. Seitdem prüft niemand mehr, ob die Verbindung wirklich zu diesem Server geht. Solche Altlasten gehören entfernt, nicht gepflegt.

Das Cheatsheet für den Alltag

Zum Schluss die Kommandos, die ich wirklich ständig benutze — als Infografik zum Aufhängen und als Referenz für die nächste Debugging-Session:

Cheatsheet: curl und wget Kommandos für Status, Header, Auth, JSON, POST, Downloads, Fortsetzen, Rate-Limit und Timing

Und hier die Anatomie eines typischen API-Aufrufs, damit die Flags nicht mehr wie Zauberzeichen wirken:

Anatomie eines curl-Befehls: curl, -sS, -u, -H, -d, -X und URL mit Bedeutung jeder Komponente
API-Antworten verstehen: Bekommst du eine JSON-Antwort, die unlesbar ist, wirf sie in den bitcalc JSON-Formatter — formatieren, validieren, Baumansicht. Und für Auth-Probleme: admin:passwort in den Base64-Encoder tippen und den Authorization-Header selbst nachrechnen — dann weißt du, ob curl oder die API das Problem ist.

Fazit

curl und wget sind keine Gegner, sie sind ein Team: curl für die Kontrolle über jeden Request, wget für die Geduld bei großen Downloads. Die wichtigsten Lektionen aus meinem Alltag: -w gibt dir Timing statt Rätselraten, -u ist Base64 und kein Schutz, --fail --retry --max-time machen Skripte ehrlich, und -k ist fast immer ein Fehler. Wer diese fünf Punkte verinnerlicht, debuggt APIs schneller als die meisten — und wer den Rest des Cheatsheets nutzt, hat das Werkzeug, das hinter jeder guten Admin-Geschichte steckt.

Das Skript des Entwicklers von damals läuft übrigens heute noch. Mit sauberen Flags, Credentials aus der Umgebung und einem --fail, das endlich die Wahrheit sagt.