HandyTools Hub

cURL Converter

Convert cURL commands to fetch, axios, or Python code

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 a headers object and a body string.
  • JavaScript axios — a config object with method, url, headers, optional data, and optional auth.
  • Python requests — an import requests, optional headers and data variables, then a requests.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 flagEffect on the parsed request
-X, --requestSets the HTTP method, uppercased
-H, --headerAdds one header, split at the first colon
-d, --data, --data-raw, --data-binary, --data-asciiAdds to the body; multiple parts joined with &
-u, --userRecords basic-auth credentials
-A, --user-agentAdds or replaces the User-Agent header
-G, --getMoves the data into the query string and uses GET
-I, --headUses HEAD
--urlSupplies 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 -d parts are concatenated with &. This usually matches application/x-www-form-urlencoded, but it will not reproduce multipart/form-data with file parts.
  • Unknown flags are dropped. A --cookie session, redirect following, or TLS bypass is not replicated in the generated code even though the request may succeed.
  • -G changes 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 -X becomes POST; add -X GET or -G if 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.

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