What this tool does
Paste a curl command and get the equivalent code in JavaScript (fetch or axios), Python (requests), Node.js (https module), or Go (net/http). The tool parses your curl command properly — handling quoted strings, multi-line continuations with backslash, all the common flags (-X, -H, -d, -F, -u, -b, --data-raw, --data-urlencode, and several others) — and produces code that does the same HTTP request from your language of choice.
This is the tool you reach for after copying a curl example from an API's documentation. Stripe, Twilio, GitHub, OpenAI, AWS — they all show curl. Most of the time you're building in something else. Manually translating the headers and body to your language takes 5 minutes and is error-prone. This takes one keypress.
What it handles correctly
- HTTP method via
-Xor implied — if you pass-dor-Fwithout an explicit-X, the method is correctly inferred as POST (same as curl itself). - Headers via
-H "Name: Value", multiple times. Order is preserved. - JSON bodies — when the body looks like JSON (starts with
{or[and parses successfully), the output uses the language's native JSON helper (JSON.stringify(...), Python'sjson=kwarg, etc.) and addsContent-Type: application/jsonif you forgot it. - Form-urlencoded bodies — recognized when the body matches
key=value&key=valueshape, with the correctContent-Typeapplied. - Multipart form data via
-F— producesFormDatain JS,files=in Python, etc. - Basic auth via
-u user:pass— converted to either anAuthorization: Basic …header (fetch, Go) or the language's auth-helper (axiosauth: {…}, Pythonauth=(…)). - Multi-line commands with
\continuations — copy-paste from a code block in the docs without manual cleanup. - Combined short flags like
-XPOSTare handled the same way curl does. - The
-Gflag for forcing GET — body data is correctly moved into the URL query string.
What it deliberately doesn't try to do
- File uploads via
-F 'file=@path'are partially supported — the field name comes through, but you need to wire up the actual file in your language (browsers' FormData can take a File from an input element; Node hasfs.createReadStream; Python hasfiles={'file': open(path, 'rb')}). - Proxy options, retries, timeouts, max-redirects aren't replicated. They're tooling-level concerns that don't translate cleanly across languages.
--insecure/-kemits a comment in the output, not an actual TLS bypass — browsers can't disable certificate verification from JavaScript, and you almost never want to in production code anyway.
Common gotchas
- Cookies copied from a browser — when you grab "Copy as curl" from DevTools, the cookie often includes session tokens that expire in minutes. The code converts fine, but the request will fail with 401/403 once the token expires. Either re-login and re-copy, or use a proper auth mechanism (Bearer token, API key) instead.
- The
--dataflag URL-decodes content but--data-rawdoesn't. If your body contains%or+, the choice between these two flags matters and the output reflects what you typed. - Multiple
-dflags get joined with&, matching curl's actual behavior.-d a=1 -d b=2becomesa=1&b=2, not two separate request bodies. - The
@prefix in-d @file.jsonmeans "read body from a file". The output preserves the literal@file.jsonas the body string — you need to replace it with actual file-reading code in your language.
Workflow tips
In Chrome DevTools, the Network tab has "Copy as curl" — right-click any request. Paste the result here. Pick your target language. Done.
For larger API integrations (more than a handful of endpoints), use a proper SDK or generate a client from the OpenAPI spec rather than translating curl examples one by one. This tool is for the quick "I need to call this one endpoint" cases — bootstrap a single request, then move on.
Common use cases
- Translate a curl example from API docs into your language
- Convert "Copy as curl" from Chrome DevTools into runnable code
- Get the Python equivalent of a JavaScript fetch you have working
- Bootstrap a one-off API call without setting up a full SDK
Frequently asked questions
What flags are supported?
<code>-X/--request</code>, <code>-H/--header</code>, <code>-d/--data</code>, <code>--data-raw</code>, <code>--data-urlencode</code>, <code>--data-binary</code>, <code>-F/--form</code>, <code>-u/--user</code>, <code>-b/--cookie</code>, <code>-A/--user-agent</code>, <code>-e/--referer</code>, <code>-G/--get</code>, <code>--compressed</code>, <code>-k/--insecure</code>. Behavior-only flags like <code>-L</code>, <code>-s</code>, <code>-v</code>, <code>-i</code>, <code>-f</code> are accepted and ignored.
What about file uploads?
The field name and value pass through correctly, but you need to wire up the actual file in your language: <code>FormData.append(name, file)</code> in JS with a real File object, <code>files={'file': open(path, 'rb')}</code> in Python, <code>fs.createReadStream(path)</code> in Node.
Why does -X POST without -d still produce a POST in the output?
curl's rule is: explicit <code>-X</code> always wins. If you pass <code>-d</code>, method is inferred as POST. With neither, GET. The converter follows the same rules.
Does it handle authentication other than basic?
Basic auth via <code>-u user:pass</code> is converted to the proper Authorization header (or auth-helper in axios/Python). Bearer tokens, API keys, etc. just come through as regular headers — if your curl had <code>-H "Authorization: Bearer xxx"</code>, the output preserves it.
What about the <code>@</code> file prefix in <code>-d @file.json</code>?
The literal <code>@file.json</code> appears as the body string in the output. Replace it with actual file-reading code: <code>fs.readFileSync(path, 'utf8')</code> in Node, <code>open(path).read()</code> in Python.