cURL to Code
cURL to Code turns a curl command into fetch, axios, Python requests, Go, PHP or Ruby in your browser. It parses the command as shell — single quotes, double quotes, ANSI-C escapes, line continuations and clustered flags — so a payload with a space or an apostrophe in it survives intact.
How does cURL to Code work?
The conversion looks trivial and is not, because a curl command is shell rather than a data format. Three things break a naive implementation, and all three are common in commands copied out of a browser's developer tools.
The quoting is the hard part
-d '{"name":"Ada Lovelace"}' is one argument containing a space. -H "Authorization: Bearer $TOKEN" contains a variable the shell has already expanded or has not. --data $'line\nbreak' uses ANSI-C quoting, where \n is a real newline — and the same characters inside ordinary single quotes are a literal backslash and an n. No regular expression can undo that, because the escaping rules differ inside each quoting style. So the command is tokenized by a small state machine that tracks which quote it is inside, and the emitters only ever see finished arguments.
Clustered flags are three different things
-sSL is three bare flags. -XPOST is one flag with its value attached. -H'X-Trace: 1' is a value-taking flag whose value contains punctuation and a space. They are told apart by walking the letters and stopping at the first one that takes a value, which is what curl's own parser does — and it is why -sSXPOST comes out as a POST rather than as six flags.
What the generated code refuses to invent
-d @payload.json reads a file at run time. The file is not in the command, so the body cannot be inlined: the generated code names the file and leaves the read for you, because guessing would produce code that silently posts the wrong payload. -k is the other deliberate omission — the generated code keeps certificate verification on and says so in a comment, since an insecure flag copied into a codebase is exactly how it ends up in production.
Everything else translates directly: -u becomes the Authorization: Basic header it actually sends, -b becomes a Cookie header, -F becomes a multipart form with the boundary left to the HTTP client, and -G moves the data into the query string where curl puts it.
curl
curl -X POST 'https://api.example.com/v1/orders' \
-H 'Content-Type: application/json' \
-d '{"total":148.5}'fetch
const response = await fetch("https://api.example.com/v1/orders", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
"total": 148.5
}, null, 2),
});
const data = await response.json();What does a curl command look like as fetch?
The command a browser's "Copy as cURL" produces, translated. The headers, the method and the body all survive the shell quoting, which is the part a naive converter gets wrong.
curl
curl -X POST 'https://api.example.com/v1/orders' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_TOKEN_HERE' \
-d '{"total":148.5}'fetch
const response = await fetch("https://api.example.com/v1/orders", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer YOUR_API_TOKEN_HERE",
},
body: JSON.stringify({
"total": 148.5
}, null, 2),
});
const data = await response.json();
A JSON body is emitted as JSON.stringify({...}) — and as the object itself for axios and Python requests — so the generated code reads as data rather than as an escaped string. The Authorization header is reproduced because it was in the command — treat the generated file as you would treat the command.
What options and edge cases does cURL to Code support?
| Parameter | Type | Default | Behaviour & edge cases |
|---|---|---|---|
| -X, --request | method | POST if there is a body | Sets the HTTP method. Without it the method is POST when the command has a body, form field or -I, and GET otherwise — which is exactly curl's own rule. |
| -H, --header | headers | none | Repeated once per header. The -H "Name;" form removes a header rather than setting one; generated code simply does not send it, and the page says so rather than inventing a value. |
| -d, --data* | body | none | Multiple -d flags are joined with &, which is what curl does. -d @file cannot be inlined — the file is not in the command — so the generated code names it and leaves the read to you. |
| --data-urlencode | body | form-encoded | The value is percent-encoded before it becomes the body, so a space or an ampersand in the value is safe. That is the whole point of the flag. |
| -F, --form | multipart | none | Becomes a multipart form. -F name=@file attaches a file part and -F name=value sends a text part; the boundary is left to the HTTP client, because setting it by hand is how a multipart request ends up malformed. |
| -u, --user | basic auth | none | Becomes the Authorization: Basic header curl actually sends, with the credential base64-encoded. It is visible in the generated code because it was visible in the command. |
| -b, --cookie | cookie header | none | A semicolon-separated cookie string becomes one Cookie header, parsed into name/value pairs so the generated code reads as data rather than as a magic string. |
| -G, --get | query string | off | Moves every -d and --data-urlencode field into the URL's query string and clears the body, which is how curl issues a GET with a long parameter list. |
| -k, --insecure | note | off | Not reproduced. The generated code verifies certificates and carries a comment saying the original did not. Copying an insecure flag into a codebase is how it survives to production. |
| --json | body + headers | none | Sets the body, Content-Type: application/json and Accept: application/json, matching the shorthand curl added in 7.82. |
| -o, -m, --retry, --proxy | ignored | — | Local output paths, timeouts, retry counts and proxy settings have no equivalent in the generated request, so they are consumed and dropped rather than mistranslated. |
| Output size | bytes | 256 KB | A command is short by nature; the ceiling exists so a pasted file is declined rather than tokenized. |
Frequently asked questions
Does it handle commands copied from Chrome or Firefox devtools?
Yes — that is the main source of the commands people bring here. Devtools emits single-quoted arguments, a backslash-newline continuation between them, and often a `--compressed` flag and a long cookie header. All three are handled: the continuation is a line break rather than content, --compressed is noted and dropped because every client here negotiates compression itself, and -b becomes a Cookie header.
What happens to -d @payload.json?
The generated code names the file and leaves the read for you to complete. It cannot be inlined: the file's contents are not in the command, and inventing a placeholder body would produce code that silently posts the wrong payload — a bug that only shows up against a real API. The tool tells you which file it saw rather than guessing.
Why is -k not carried over?
Because copying it is how an insecure flag reaches production. The generated code keeps certificate verification on and carries a comment saying the original disabled it, so the decision stays visible and deliberate. If you genuinely need it, the comment says where to change it — and in Node it is one environment variable rather than a code change.
How are shell variables and escaped characters handled?
Variables are left as written, because the shell has already expanded them by the time you paste the command — a literal $TOKEN in the text means the variable was not expanded, so it stays as a placeholder you can see. Escaping is interpreted properly: inside double quotes a backslash only escapes the five characters POSIX says it does, inside single quotes nothing is escaped at all, and $'…' is ANSI-C quoting where \n is a real newline.
Which target should I pick?
fetch if the code is going into a browser or Node 18+, which is most cases now. axios when the project already uses it, since it handles JSON serialisation and error statuses for you. Python requests for a script, Go for a service, PHP or Ruby when that is the codebase. All six produce the same request; they differ only in how much ceremony the language needs.
Is my command sent anywhere?
No. Parsing and generation both run in this tab. That matters because a curl command frequently contains a live API key, a session cookie or a bearer token — the Authorization header in the sample above is exactly that. Nothing is transmitted, and there is no API route for it to be transmitted to.