cURL to Fetch Converter

Parse a curl command and generate browser or Node fetch() code using async/await — methods, headers, JSON bodies, cookies and basic auth included.

Paste your curl command

How it works

About cURL to Fetch Converter

A browser tab cannot execute curl — it is a command-line tool — and hand-writing the equivalent fetch() call is easy to get wrong. This converter turns a curl command copied from docs or shell history into modern async/await fetch code you can paste straight into a script, a test, or the DevTools console.

The two differ in defaults: curl sends Content-Type: application/x-www-form-urlencoded for -d payloads, while fetch() sets no content type unless you add one; HTTP headers are case-insensitive, so the converter preserves the exact casing you typed. The mapping is not complete — options like --cookie-jar, TLS certificates (-k, --cacert) and retries have no fetch equivalent and are skipped.

What the generated call actually contains

Output is a bare `fetch(url)` when the parsed command has no method, headers or body, and an options object otherwise. The body appears only when `-d` or a variant was present, and only when it parses as JSON after trimming — the payload is re-serialised through `JSON.stringify`, so key order and number formatting come from a JSON round trip rather than from your text. A `Content-Type: application/json` header is added only when you supplied none, and the output carries a comment marking that the tool made that decision.

Authentication and cookies are folded in. `-u user:pass` becomes an `Authorization: Basic <base64>` header computed from the UTF-8 bytes of the credential, and it is skipped when an `Authorization` header already exists so an explicit bearer token is never overwritten. A `-b` cookie string is appended to an existing `Cookie` header or added as a new one, and header casing is preserved exactly as typed rather than normalized.

Two headers in the output are forbidden to browsers

The Fetch specification designates certain names as forbidden header names, and the browser strips them from the request before it leaves. `User-Agent` is the important one: curl's `-A` has no client-side equivalent in a page, because a script cannot set it and the browser replaces it with its own value. `Cookie` is on the same list — setting it from `fetch` is ignored, which means the merged `Cookie` header in generated code is effectively documentation of what curl would have sent, not something a page can actually deliver.

Credentials are governed separately. `credentials` defaults to `same-origin`, so a cross-origin request drops cookies and any `Authorization`-derived session silently, and you need `credentials: 'include'` plus a matching `Access-Control-Allow-Credentials` header and a specific origin rather than a wildcard. That option is not emitted, so treat the generated call as same-origin unless you add it yourself.

CORS, timeouts and status handling are left to you

Nothing in the output can bypass CORS, and a preflight is triggered by the request itself: a `POST` with `Content-Type: application/json` is not a simple request, so the browser sends an `OPTIONS` probe first and the server must answer it with the right `Access-Control-Allow-*` headers. The generated code also has no `try`/`catch` around the promise, so a rejected fetch surfaces as an unhandled rejection.

Three gaps matter when the source command was more careful than fetch. There is no timeout — fetch has no timeout option, so a hung request hangs, and curl's `--max-time` needs an `AbortSignal.timeout()` or a manual `AbortController` to be equivalent. A form-encoded `-d 'a=1&b=2'` is emitted as a plain string body with no content type, where curl sends `application/x-www-form-urlencoded`. And the tail calls `response.json()` unconditionally, which throws on a 204 or an HTML error page where curl would print whatever body arrived. In Node 18 and later the same code runs without CORS enforcement or forbidden-header filtering, so it behaves considerably closer to the original command than it does in a page.

Next steps

Frequently Asked Questions

How do I convert curl to JavaScript fetch?
Paste a curl command into the input and click Convert. The tool parses the URL, method, headers, and body, then outputs an equivalent JavaScript fetch() call. Both async/await and Promise.then() styles are available.
Does it handle authentication headers?
Yes. Basic auth, Bearer tokens, API keys in headers, and custom headers are all preserved in the generated fetch code. Form data and JSON bodies are handled appropriately.
Is my data sent to a server?
No. Every tool on jsonversal runs entirely in your browser using the Web Crypto API, File API, and Clipboard API. Nothing is ever uploaded — not even the JSON you paste in.
Do I need an account or API key?
No signup, no email, no API key. All tools are free to use with no signup required.
Can I use these tools offline?
Yes. Once the page loads, all tools work offline. There are no external API calls or CDN dependencies at runtime.
🔒
Your data never leaves your device

All processing happens in your browser. No uploads, no tracking, no servers. Your API keys, configs, and private payloads stay private — 100% client-side.

esc
↑↓ navigate ↵ open esc close