cURL to fetch Converter

Paste a curl command — for example from your browser's "Copy as cURL" — and get equivalent fetch() code for the browser, Node.js, Deno or Bun. Parsing happens in this tab, so bearer tokens are never uploaded.

cURL → JavaScript fetch

Input

Settings

History

Load from URL

From a terminal command to fetch()

API docs, support tickets and DevTools all hand you requests as curl commands, but your front end or Node script needs fetch. Translating by hand is where bugs creep in: a forgotten header, a body that should have been JSON-stringified, or a redirect that curl did not follow but fetch does. This converter parses the command the way curl does and emits code that sends the same request.

It reads commands copied from bash or zsh (with \ line continuations and $'…' strings), from Windows cmd (^ escapes, as in Chrome’s “Copy as cURL (cmd)”) and from PowerShell (backtick continuations).

How curl options become fetch options

  • -X sets method; without it the method is inferred just as curl does (POST when there is a body, HEAD for -I, PUT for -T). GET is left implicit.
  • -H headers go into a headers object. A header repeated with the same name is folded into one comma-separated value.
  • -d, --data-raw and --data-binary become body. When the content type is JSON and the body is a JSON object or array, the code uses JSON.stringify({...}) with a readable object literal; otherwise the exact string is sent. Several -d flags are joined with &, and curl’s implied application/x-www-form-urlencoded header is written out explicitly.
  • --json sets the body plus Content-Type and Accept: application/json.
  • -G moves the data into the query string; --data-urlencode and --url-query are encoded the way curl encodes them.
  • -F builds a FormData; file fields (-F [email protected]) get a placeholder Blob and a TODO comment, since a web page cannot read your disk.
  • -u user:pass becomes an Authorization: Basic header built with btoa; --oauth2-bearer becomes a Bearer header.
  • -m/--max-time becomes signal: AbortSignal.timeout(ms).

Redirects and other differences

curl does not follow redirects unless you pass -L, while fetch follows them by default. To keep the behaviour identical, the generated code sets redirect: 'manual' without -L (with a comment explaining why) and redirect: 'follow' with it.

Some curl features have no fetch equivalent, and the converter says so instead of silently dropping them:

  • -k/--insecure: fetch always verifies TLS certificates; a warning and a comment are added.
  • --connect-timeout and -x proxies: noted in comments (in Node.js, an undici ProxyAgent handles proxies).
  • A GET or HEAD with a body: fetch refuses to send it, so the body is left out with a warning — you probably meant -G.
  • Browsers block scripts from setting Cookie and Referer; a comment notes that they only take effect in server-side runtimes.

Flags that only affect curl’s own output (-s, -v, -i) are ignored, and options such as -o or --retry produce an info note. The result is formatted with Prettier and prints the status and response text.

Credentials stay on your machine

Copied commands nearly always contain secrets: session cookies, API keys, bearer tokens. That is why the conversion runs entirely client-side. For a promise-based alternative with automatic JSON handling, see cURL to Axios; to tidy the generated code further, use the JavaScript formatter.

Examples

JSON POST with a bearer token

The JSON body becomes JSON.stringify of a JavaScript object literal, and redirect is set to manual because there is no -L.

Input
curl -X POST 'https://api.example.com/v1/orders?expand=items' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc' \
  -d '{"customer":"cus_42","items":[{"sku":"KB-104","qty":1}]}'
Output
const response = await fetch('https://api.example.com/v1/orders?expand=items', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc',
  },
  body: JSON.stringify({
    customer: 'cus_42',
    items: [{ sku: 'KB-104', qty: 1 }],
  }),
  redirect: 'manual', // curl follows redirects only with -L
});

console.log(response.status);
console.log(await response.text());
Open this example in the tool

Form login with basic auth and a timeout

The two -d values are joined with &, -u becomes a Basic Authorization header, and --max-time becomes AbortSignal.timeout(10000).

Input
curl -L -u admin:s3cret --max-time 10 https://intranet.example.com/login \
  -d 'user=aisha' -d 'remember=1'
Output
const response = await fetch('https://intranet.example.com/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    Authorization: 'Basic ' + btoa('admin:s3cret'),
  },
  body: 'user=aisha&remember=1',
  redirect: 'follow',
  signal: AbortSignal.timeout(10000),
});

console.log(response.status);
console.log(await response.text());
Open this example in the tool

Chrome "Copy as cURL (cmd)"

Windows caret escaping is decoded, and the cookie header comes with a reminder that browsers do not allow fetch to set it.

Input
curl ^"https://api.example.com/v1/me^" ^
  -H ^"accept: application/json^" ^
  -H ^"cookie: session=abc123; theme=dark^"
Output
// Browsers do not let fetch set Cookie or Referer headers; they are sent as written in Node.js.
const response = await fetch('https://api.example.com/v1/me', {
  headers: {
    accept: 'application/json',
    cookie: 'session=abc123; theme=dark',
  },
  redirect: 'manual', // curl follows redirects only with -L
});

console.log(response.status);
console.log(await response.text());
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
"-Uri" is PowerShell's Invoke-WebRequest syntax, not curlIn Windows PowerShell, curl is an alias for Invoke-WebRequest, and the command uses its parameters.Copy the request as cURL (bash) or (cmd) instead, or rewrite it with -H, -d and -X.
fetch cannot send a body with GET; the body is left outThe curl command sends data with GET (-X GET -d …), which fetch does not allow.Use -G so the data goes into the query string, or switch the method to POST.
fetch has no option to skip TLS certificate checks (-k); the generated code verifies certificatesThe command uses -k/–insecure, typically against a self-signed development server.Trust the certificate in your OS or Node (NODE_EXTRA_CA_CERTS) rather than disabling verification.
This single-quoted string is never closedA quote in the pasted command is unbalanced, often because the command was cut off.Copy the full command again, including the closing quote.
Shell variable $TOKEN cannot be expanded here and is kept as literal textA double-quoted argument refers to an environment variable.Replace the variable in the generated code with the real value or a process.env lookup.

Frequently asked questions

Does the generated code work in Node.js?

Yes. Node 18 and later ship fetch globally, and the code uses top-level await, so run it as an ES module (.mjs) or wrap it in an async function.

Why is redirect set to manual?

curl only follows redirects with -L, while fetch follows them by default. Setting manual keeps the generated request behaving like your command.

How are file uploads with -F handled?

A FormData is built with a placeholder Blob for each file and a TODO comment. Replace it with a File from an input element or a Blob read in Node.

Is my API token sent to PasteKit?

No. The command is parsed and converted in your browser, and nothing is transmitted.

Related tools