From curl to fetch, axios, and Python: the API integration workflow
Every API doc uses curl examples. Every codebase uses something else. Here's how to translate curl commands correctly โ headers, auth, JSON bodies, and the flags that don't map cleanly.
Why curl became the API lingua franca
Every API vendor docs their endpoints in curl. Postman exports as curl. Chrome DevTools has "Copy as cURL" in the Network tab. Stack Overflow answers about "how do I call X API" almost always paste curl.
The reason: curl is the shortest, most portable, executable-in-one-line way to describe an HTTP request. But nobody ships production code that calls curl. You need it in JavaScript (fetch, axios), Python (requests, httpx), Go, Rust, or whatever your stack is.
That translation โ curl to code โ is the workflow this post is about.
The core curl flags and their mappings
-X POST (--request): the HTTP method.
// fetch
fetch(url, { method: "POST" })
Note: if you pass -d (data), curl defaults to POST automatically, so -X becomes redundant. fetch doesn't have this shortcut.
-H "Content-Type: application/json" (--header): a request header.
fetch(url, { headers: { "Content-Type": "application/json" } })
-d '{"name":"Ada"}' (--data): the request body. Sends as application/x-www-form-urlencoded by default in curl; use --data-raw to send exactly as-is.
fetch(url, { method: "POST", body: JSON.stringify({ name: "Ada" }) })
--json '{"name":"Ada"}': shortcut in curl 7.82+ โ sets Content-Type and Accept headers to application/json and POSTs the body.
-u user:pass (--user): HTTP Basic auth. Turns into an Authorization: Basic <base64> header.
fetch(url, { headers: { Authorization: "Basic " + btoa("user:pass") } })
-b cookie=value (--cookie): send a cookie. Turns into a Cookie: header.
-A "MyBot/1.0" (--user-agent): short for -H "User-Agent: MyBot/1.0".
The flags that don't translate cleanly
-L(--location): follow redirects. In fetch this is the default (redirect: 'follow'). In axios, controlled bymaxRedirects. Pythonrequestsfollows by default.-k(--insecure): skip TLS verification. Never do this in production code. In Node fetch:agent: new https.Agent({ rejectUnauthorized: false }). Python:verify=False.-o file.json(--output): write to a file. In JS, you'dawait res.arrayBuffer()and pipe to fs.-v(--verbose): debugging output. No JS equivalent โ use browser DevTools or Node'sNODE_DEBUG=http.-i/-I: include headers in output / HEAD request only.--compressed: request gzip. Fetch does this by default; axios does too.
If you're pasting a curl with these flags and getting subtly different behavior in JS, one of them is the culprit.
The three-second workflow
- Copy as cURL from Chrome DevTools (right-click any request โ Copy โ Copy as cURL).
- Paste into cURL Converter.
- Pick fetch, axios, or Python โ code appears with the right headers, method, and body wiring.
- Adjust variable names โ the tool doesn't know your
API_URLenv var.
For most API integrations, that's 30 seconds from doc to working code.
When the API returns wrong status codes
Every debug session eventually hits a mysterious 4xx. The reference:
- 400 โ malformed request. Bad JSON, missing required field.
- 401 โ auth missing or expired. Check the token.
- 403 โ auth valid but not allowed. Different from 401 โ re-auth won't help.
- 404 โ wrong URL. Check the base URL and route.
- 422 โ well-formed but semantically invalid. Common in modern JSON APIs.
- 429 โ rate limited. Check
Retry-Afterheader.
HTTP Status Codes has the full reference. Search by code or by keyword.
Auth flows are the biggest translation traps
Bearer tokens (JWT):
curl -H "Authorization: Bearer eyJhbG..." https://api.example.com/me
Maps cleanly to any language. The trap: when the JWT expires, curl gives you a 401 immediately, but your library may not โ axios interceptors are the usual place to add refresh logic.
To inspect what's inside the token during debugging, use JWT Decoder โ locally, so you don't paste production credentials into a random online tool.
OAuth flows: curl can't do the redirect steps. Use a library or the vendor's SDK. Once you have the access token, the curl โ fetch pattern above works.
API keys in query strings vs headers: vendors vary. AWS uses signed URLs, Stripe uses Authorization: Bearer, OpenAI uses Authorization: Bearer, older APIs use ?api_key=. Read the auth docs; don't assume.
Multi-part uploads
curl handles multi-part uploads with -F:
curl -F "file=@photo.jpg" -F "caption=Sunset" https://api.example.com/upload
The JavaScript equivalent uses FormData (not JSON.stringify):
const fd = new FormData();
fd.append("file", fileInput.files[0]);
fd.append("caption", "Sunset");
await fetch(url, { method: "POST", body: fd });
// Don't set Content-Type โ the browser adds the boundary automatically
The single most common mistake: setting Content-Type: multipart/form-data yourself. The browser must set it because it needs to include the boundary. Let it.
Related workflows
- HTTP Status Codes โ for the "why is this 422?" moment.
- JWT Decoder โ for inspecting tokens without leaking them.
- JSON Formatter โ for eyeballing API responses.
- User-Agent Parser โ when the API cares about your UA.
Tools mentioned in this post
Related reading
HTTP status codes that actually matter for API developers in 2026
You know 200 and 500. But the difference between 401 vs 403, 400 vs 422, and 502 vs 503 decides whether your API is professional or amateur. Here's the short list that matters.
User-Agent strings in 2026: parsing, Client Hints, and privacy
The User-Agent string is a mess โ Chrome pretends to be Safari, Edge pretends to be Chrome. But it's still what your analytics reads. Here's how to parse it, when to trust it, and where Client Hints are taking us.
JWT explained: what actually goes inside that token
Every login flow you touch these days involves JWTs, but 'JSON Web Token' hides a lot. Here's the three-part structure, the security pitfalls, and when not to use them.
Shan builds 712 Tools. He holds a Master's degree in Mechanical Engineering and now works as a Software Engineer, shipping browser-based developer utilities out of Ontario, Canada. Learn more ยท 712studiogames@gmail.com