cURL to fetch(): Headers, Bodies, Auth and Multipart Examples
Reviewed September 3, 2026 · Maintained by William
cURL and JavaScript fetch() can express many of the same HTTP requests, but the translation is not purely mechanical. Shell quoting, browser CORS and multipart boundaries are the places most likely to break a copy-and-convert workflow.
GET with headers
curl 'https://api.example.com/items?page=2' \
-H 'Accept: application/json'
const response = await fetch('https://api.example.com/items?page=2', {
headers: { Accept: 'application/json' }
});
POST JSON
curl -X POST 'https://api.example.com/items' \
-H 'Content-Type: application/json' \
-d '{"name":"Ada","active":true}'
const response = await fetch('https://api.example.com/items', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Ada', active: true })
});
Bearer authentication
Move the Authorization header, but do not paste a real production token into documentation or commit it to source:
headers: { Authorization: `Bearer ${token}` }
Multipart/form-data
With FormData, let the browser set the multipart boundary. Copying a cURL Content-Type: multipart/form-data; boundary=... value into fetch can create a mismatch.
const form = new FormData();
form.append('name', 'Ada');
form.append('file', fileInput.files[0]);
await fetch('/upload', { method: 'POST', body: form });
The biggest environment difference: CORS
A terminal cURL request is not constrained by browser CORS. The same URL can work perfectly in cURL and fail from front-end JavaScript until the API explicitly permits that browser origin. That does not mean the converter produced invalid JavaScript.
Translation limits
cURL supports TLS, proxy, retry, cookie-jar, certificate and low-level transfer flags that have no direct browser-fetch equivalent. Treat generated code as a readable starting point, not a proof that every original transport detail was preserved.
Try the cURL to Fetch Converter with dummy URLs/tokens, then compare the output with your target runtime.
References
Translate the request model, not just the text
A reliable conversion starts by identifying the URL, method, headers and body semantics in the cURL command. Shell syntax is only the container. For example:
curl 'https://api.example/items' \
-X POST \
-H 'Authorization: Bearer TEST_TOKEN' \
-H 'Content-Type: application/json' \
--data '{"name":"Ada","active":true}'
A fetch equivalent can be:
const response = await fetch('https://api.example/items', {
method: 'POST',
headers: {
'Authorization': 'Bearer TEST_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'Ada', active: true })
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
Form encoding is different from JSON
A command using --data-urlencode or a form content type should usually become URLSearchParams, not JSON. Preserve the server’s expected representation rather than changing body format just because JavaScript makes JSON convenient.
const body = new URLSearchParams({
username: 'ada',
mode: 'preview'
});
Multipart: let the runtime choose the boundary
For multipart form data, use FormData. Do not copy a raw Content-Type: multipart/form-data; boundary=... from a captured cURL command while letting fetch create a different body. When using FormData, the browser/runtime normally adds the correct content type and boundary.
Browser fetch has constraints terminal cURL does not
- CORS can block browser JavaScript even when the terminal request succeeds.
- Browsers restrict some headers for security reasons.
- Cookie behavior depends on credentials mode, cookie attributes and same-site rules.
- TLS client certificates, proxies and low-level transport flags do not map cleanly to browser fetch.
- Redirect and response streaming behavior can differ from cURL flags.
Authentication hygiene
Do not paste production bearer tokens, basic-auth passwords or signed URLs into public documentation or issue reports. When converting a command, replace credentials with placeholders first. In browser applications, avoid shipping long-lived secrets in frontend JavaScript because users can inspect the code and network traffic.
Conversion review checklist
After using the cURL to fetch() converter, compare the generated method, URL/query string, headers, body encoding and authentication intent with the original. Then test against a safe development endpoint. Treat uncommon cURL options as a manual-review signal rather than assuming every flag has a browser equivalent.