Skip to content

curl

The universal HTTP client. Every ML API can be probed with curl before you write a line of Python — it's the fastest way to check a route, a header, or a 500 error.

Table of Contents

Installation / Setup

# macOS (ships built-in) / Linux (usually preinstalled)
curl --version

# Windows 10+: curl.exe ships with Windows; in PowerShell use curl.exe
# (plain `curl` is aliased to Invoke-WebRequest — use curl.exe to avoid surprises)

# install on Debian/Ubuntu if missing
sudo apt install curl
Platform Invoke
macOS / Linux curl https://api.example.com
Git Bash (Windows) curl ...
PowerShell curl.exe ... (avoid the curl alias)
CMD (Windows) curl ...

Core Syntax

curl [options] URL
Option Short Purpose Example
--request -X HTTP method (usually unnecessary) -X POST
--data -d Body data (sets POST) -d '{"x":1}'
--header -H Request header -H "Content-Type: application/json"
--json Shortcut: JSON body + correct headers --json '{"x": 1}'
--output -o Write body to a file -o resp.json
--include -i Show status + headers in output -i
--silent -s No progress bar -s
--fail -f No output on HTTP errors (exit code nonzero) -f
--verbose -v Full request/response debug -v
--user -u Basic auth -u user:pass
--header -H Bearer token -H "Authorization: Bearer $TOKEN"
--form -F multipart form / file upload -F "file=@image.jpg"
--max-time -m Timeout seconds -m 30
--connect-timeout Connect timeout --connect-timeout 5

Method notes

  • curl URL alone sends GET.
  • -d/--json switches the method to POST automatically — no -X POST needed.
  • Use -X PUT/-X DELETE only when the method isn't implied (and mind the -X + -d interplay on redirects).

Common Operations

# GET with query string
curl "http://localhost:8000/search?q=cat&limit=5"

# POST JSON — the standard way to hit a /predict endpoint
curl -X POST http://localhost:8000/predict \
  -H "Content-Type: application/json" \
  -d '{"text": "refund request"}'

# same, modern shorthand
curl --json '{"text": "refund request"}' http://localhost:8000/predict

# read the JSON body from a file (cleaner for long payloads)
curl -X POST http://localhost:8000/predict \
  -H "Content-Type: application/json" \
  -d @payload.json

# see status code, headers and body together
curl -i http://localhost:8000/health

# upload a file as multipart form data (image classification)
curl -X POST http://localhost:8000/classify -F "file=@dog.jpg"

# send a raw file as the body
curl -X POST http://localhost:8000/embed -H "Content-Type: text/plain" --data-binary @doc.txt

Authentication

# Bearer token (most common for AI APIs)
curl -H "Authorization: Bearer sk-123..." https://api.openai.com/v1/chat/completions \
  --json '{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "hi"}]}'

# API key header
curl -H "X-API-Key: $API_KEY" https://api.example.com/v1/models

# Basic auth
curl -u username:password https://api.example.com/private

Practical Examples

Probe a local model server end-to-end

# 1) health check — expect {"status": "ok"}
curl -i http://localhost:8000/health

# 2) real prediction
curl --json '{"tenure": 12, "monthly_charges": 89.5, "contract": "month", "support_calls": 3}' \
  http://localhost:8000/predict

# 3) deliberate error — what does a bad payload return?
curl -i --json '{"tenure": "abc"}' http://localhost:8000/predict

Stream a chat completion (OpenAI-compatible)

curl https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4o-mini",
       "messages": [{"role": "user", "content": "Explain PCA in one line"}],
       "stream": true}'

Headers-only probe

curl -sI https://huggingface.co   # -I = HEAD request: headers only

Follow redirects and save output

curl -L -o model_card.json https://huggingface.co/api/models/gpt2

Common Patterns

Pretty-print responses

curl -s http://localhost:8000/health | python -m json.tool

# jq gives you field extraction
curl -s http://localhost:8000/predict --json '{"text":"hi"}' | jq .label

Exit codes tell you success/failure

curl -fsS --json '{"text": "hi"}' http://localhost:8000/predict > out.json \
  && echo "HTTP 2xx" || echo "HTTP error (or network failure)"

-f makes curl return a nonzero exit code on HTTP 4xx/5xx — essential in shell scripts and CI.

Timeout so scripts never hang

curl -m 10 -fsS http://localhost:8000/predict --json '{"text": "hi"}'

Test with a real token from env (never inline secrets)

curl -fsS -H "Authorization: Bearer ${API_TOKEN:?set API_TOKEN}" https://api.example.com/v1/models

Best Practices

  • Always set Content-Type: application/json (or use --json) when sending a JSON body.
  • Use -f in scripts so 4xx/5xx responses break the pipeline instead of passing silently.
  • Put JSON in a file (-d @payload.json) for anything longer than one line.
  • Use -m timeouts on every remote call.
  • Keep secrets in environment variables, never in the command (shell history risk).
  • -v when debugging; it shows the exact request curl sends (helps find typos).
  • Prefer --json over -d + explicit header for modern curl (≥ 7.82).

Common Mistakes

Mistake Fix
curl URL -d '{"a":1}' without Content-Type Server sees application/x-www-form-urlencoded — add the header or use --json
PowerShell curl = Invoke-WebRequest, which mangles output Use curl.exe in PowerShell
-X POST + -d on a URL that redirects Redirect becomes POST too; use --data only and let it infer, or add --location-trusted
Missing -f: scripts "succeed" on 500s Add -f and check exit code
JSON quoting breaks under nested quotes Write payload to a file, use -d @payload.json
No timeout against a hung model endpoint Add -m 30
Windows CMD escaping of " and % Use single-quote-free payload files (@payload.json) or Git Bash

Troubleshooting

Symptom Cause / Fix
curl: (7) Failed to connect Nothing listening on that host:port — start the server, check the port
curl: (60) SSL certificate problem Self-signed local cert; use -k only for local testing (never in prod)
curl: (35) SSL connect error Wrong protocol (http vs https) or proxy interference
Empty body on a 500 Server crashed after headers; run server with logs, use -v to see headers
Could not resolve host Typos, no DNS, or you're offline
Response arrives but is truncated Use -L for redirects or -m longer timeout
Malformed JSON from server You posted with wrong Content-Type; check with -v
  • REST API — endpoints and methods you're hitting
  • HTTP — status codes and headers semantics
  • python-requests — the Python equivalent for scripts
  • FastAPI / Flask — the servers you test with curl
  • postman — GUI alternative for exploratory testing
  • JSON — payload shapes and escaping
  • bash — scripting curl inside pipelines

Official Documentation

Last Updated

2026-09-06 — Initial version.