cURL Converter
Convert cURL commands to fetch, axios, or Python code
Some parts of the command were skipped:
Paste a cURL command and this converter parses it into a structured request, then writes that request as runnable code in three different HTTP clients. It is built for the everyday case: copying a request out of Chrome DevTools, an API reference page, or a bug report, then dropping it into application code without hand-translating the method, headers, and JSON escaping.
What the Converter Actually Emits
Every conversion produces exactly three outputs, each on its own tab:
- JavaScript
fetch— the browser-native API, using aheadersobject and abodystring. - JavaScript
axios— a config object withmethod,url,headers, optionaldata, and optionalauth. - Python
requests— animport requests, optionalheadersanddatavariables, then arequests.request(...)call.
There is no cURL-to-Go, Ruby, PHP, C#, or HTTPie output, and no reverse “code to cURL” direction. All three snippets are generated in the same pass, so switching tabs is instant and no second conversion is needed.
Each target keeps its own idioms rather than sharing one generic template. fetch omits the method field when the request is a plain GET and appends a .then(...) chain; axios always writes a config object and lowercases the method name; Python builds named headers and data variables before the call. Because the generator works from the same parsed request, the URL, header names, and body string are identical across all three — only the syntax around them changes.
How to Use
Paste the full command, starting with curl. The tokenizer understands backslash-newline continuations, single-quoted strings, and double-quoted strings with escaped quotes, so a multi-line DevTools copy works unchanged. Click Convert, then read the warnings panel if one appears. Switch tabs and copy the snippet you need. Parsing and code generation both happen in the page, so the command and any credentials it contains stay on your device.
The converter is tolerant by design: a DevTools command that spans a dozen lines with tabs, trailing backslashes, and mixed quote styles parses exactly as the browser sent it. If the result looks wrong, the warnings list is the first place to check, because it names every token the parser could not classify. Copy buttons sit above each output pane, and the copied text matches what you see, including the .then chain on the fetch snippet.
Worked Example: One DevTools Command, Three Targets
The sample bundled with the tool is a typical “Copy as cURL” request:
curl 'https://api.example.com/v1/users' \
-H 'accept: application/json' \
-H 'authorization: Bearer your-token-here' \
-H 'content-type: application/json' \
--data-raw '{"name":"Alice","role":"developer"}' \
--compressed
The parser derives POST because a -d-family flag is present and no -X overrides it. The URL stays as written, the three headers are kept in order, and the body is the exact JSON string. One warning is reported: Unknown flag: --compressed.
For fetch, the notable parts are a method field, a headers object, and body as a quoted JSON string:
fetch("https://api.example.com/v1/users", {
method: "POST",
headers: { "accept": "application/json", "authorization": "Bearer your-token-here", "content-type": "application/json" },
body: "{\"name\":\"Alice\",\"role\":\"developer\"}",
});
The axios version mirrors this with method: "post", url, headers, and data. The Python version declares headers = {...}, data = '...', then calls requests.request("POST", "https://api.example.com/v1/users", headers=headers, data=data). In every target the body is a string, not a parsed object; the converter preserves the payload verbatim rather than reinterpreting it.
Supported Flags and What Falls Through
| cURL flag | Effect on the parsed request |
|---|---|
-X, --request | Sets the HTTP method, uppercased |
-H, --header | Adds one header, split at the first colon |
-d, --data, --data-raw, --data-binary, --data-ascii | Adds to the body; multiple parts joined with & |
-u, --user | Records basic-auth credentials |
-A, --user-agent | Adds or replaces the User-Agent header |
-G, --get | Moves the data into the query string and uses GET |
-I, --head | Uses HEAD |
--url | Supplies the URL explicitly |
Anything not in that table — --compressed, --insecure, -k, -L, --max-time, cookie jars, -F file uploads, and so on — is deliberately not converted. Those flags are collected into the warnings list above the output, so you can see exactly what was skipped and still use the generated code. A header without a colon, or a value flag with no argument, also produces a warning rather than an error. The only hard failure is a command with no detectable URL, which reports that no URL was found.
How Authentication Is Rewritten
Credentials from -u user:password become the idiomatic mechanism for each target. fetch gets "Authorization": "Basic " + btoa("user:password"); axios gets auth: { username: "user", password: "password" }; Python gets auth=("user", "password"). If the command already contains an Authorization header, the generator leaves that header alone and does not synthesize basic auth on top of it. Because credentials are written into the output, a copied snippet that used -u should be treated as sensitive.
Common Mistakes and Limitations
- Multiple
-dparts are concatenated with&. This usually matchesapplication/x-www-form-urlencoded, but it will not reproducemultipart/form-datawith file parts. - Unknown flags are dropped. A
--cookiesession, redirect following, or TLS bypass is not replicated in the generated code even though the request may succeed. -Gchanges the meaning of data. The joined data moves into the query string, and the output request has no body at all.- Method inference can surprise you. A command with a body and no
-XbecomesPOST; add-X GETor-Gif you actually wanted a GET. - The body is always a string. For a clean object literal, paste the output into your editor and replace the escaped string yourself.
Related Tools
Frequently Asked Questions
Which output languages can I generate?
Exactly three: JavaScript fetch, JavaScript axios, and Python requests. There is no cURL-to-Go, Ruby, PHP, C#, or HTTPie output, and no reverse direction that turns code into cURL. All three snippets are produced in the same pass, so switching tabs does not require converting again.
What happens to flags like --compressed that the converter doesn't understand?
They are collected into a warnings list shown above the output instead of failing the conversion. Flags such as --compressed, --insecure, -k, -L, --max-time, cookie jars, and -F file uploads are not translated; the warnings tell you exactly what was skipped.
How are multiple -d or --data flags handled?
Each value is appended to the body and the parts are joined with an ampersand, which matches how cURL sends repeated data flags. With -G or --get, the joined data is instead appended to the URL as a query string and no request body is emitted.
How does -u user:password get converted?
Basic auth becomes idiomatic per target: fetch gets an Authorization header built with btoa, axios gets auth: { username, password }, and Python gets auth=("user", "password"). If the command already has an Authorization header, that header is kept and basic auth is not added again.
How is the HTTP method decided?
An explicit -X/--request wins. Otherwise -I/--head means HEAD, a data flag with no -G means POST, and everything else is GET. A body-carrying command with no -X therefore becomes POST, which is the most common surprise.
What is the only error that stops a conversion?
A command with no detectable URL. Unknown flags, malformed headers without a colon, and value flags missing their argument only produce warnings; the generated code is still produced.
Reviewed by the HandyTools Hub team · Last updated