cURL · Code generation · Python · JavaScript
Convert cURL to Python, JavaScript and other code
Turn a cURL command into a request and then into Python, JavaScript or other code. Covers -X, -H, -d, --data-raw, -u, -F, -k, -L and --compressed, and copying cURL from browser devtools.
To convert a cURL command to Python, JavaScript or another language, parse it into its parts (method, URL, headers, body, auth and options) and rewrite each part with the target library. In Swastik Codes you paste the cURL command into the URL bar or the import dialog, which turns it into an editable request, then open the Code snippet panel and pick one of 30 targets, including Python Requests, JavaScript fetch, Axios, Go, Java and C#. This guide shows both steps and explains what each common cURL flag means in Python requests and fetch, so you can also convert by hand.
Step 1: get a cURL command
You usually already have one: from API documentation, a teammate's message, a terminal history or a bug report. If the request comes from a website or web app, the browser can produce one for you.
Copy as cURL from browser devtools
- Chrome and Edge: open DevTools (F12), go to the Network tab, reload or trigger the request, right-click it and choose Copy → Copy as cURL. On Windows there are two variants, Copy as cURL (cmd) and Copy as cURL (bash).
- Firefox: in the Network tab, right-click the request and choose Copy Value → Copy as cURL. On Windows, Firefox also offers POSIX and Windows variants.
- Safari: enable the Develop menu, open Web Inspector, go to Network, right-click the request and choose Copy as cURL.
A copied command contains every header the browser sent, including Cookie and Authorization. Treat it like a password: do not paste it into public issues or chat channels, and remove headers you do not need (sec-ch-ua, sec-fetch-*, priority and similar browser-only headers rarely matter to an API).
If you want many requests at once rather than one, save the whole Network log as a HAR file instead; Swastik Codes imports HAR files as a collection.
Step 2: import the cURL command
There are two ways in.
Paste into the URL bar. Open a new HTTP request in the app and paste the full command where the URL goes. It is recognised because it starts with curl, and the method, URL, query parameters, headers, body, auth and relevant settings are filled in. A short confirmation appears.
Use the import dialog. Open the command palette (Ctrl+K or Cmd+K) and run Import cURL / paste raw text…, or open Import and paste the text. The import dialog is the better choice for commands copied from Windows or for several commands at once:
- It understands POSIX quoting (
'…',"…"and$'…'strings) and` line continuations, thecmdflavour with^` escapes that browsers produce on Windows, and PowerShell backtick continuations. - Several commands in one paste become one collection with a request per command.
- Anything it cannot carry over is reported as a warning instead of being dropped silently, for example a proxy (
-x), client certificates (--cert,--key,--cacert) or a cookie file. Proxies and certificates are configured in the app's settings instead.
Here is a typical command to try:
curl -X POST 'https://httpbin.org/post?source=docs' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer abc123' \
--data-raw '{"sku":"A-1","quantity":2}' \
--compressedAfter the import you have a POST request with a source=docs query parameter, two headers and a raw JSON body. Send it to check that it behaves as in your terminal. Sending from the web app needs a free account, and the target must be publicly reachable; for localhost see how to test a localhost API.
How each cURL flag is imported
| cURL flag | What it means in curl | What the import does |
|---|---|---|
-X, --request | Sets the method | Sets the request method |
-H, --header | Adds a header | Adds a row on the Headers tab |
-d, --data | Sends data, implies POST; default type application/x-www-form-urlencoded | Body as form fields, or raw JSON/text when the data is JSON or a content type says so |
--data-raw | Like -d, but @ is not treated as a file name | Same as -d, value kept as typed |
--data-binary | Sends data exactly, no newline stripping | Raw body, or a file body for @file |
--data-urlencode | URL-encodes the value | Form field, encoded |
--json | JSON body plus JSON Content-Type and Accept | Raw JSON body and both headers |
-F, --form | multipart/form-data field; @file attaches a file | form-data body with text and file fields |
-u, --user | Basic auth credentials | Authorization tab set to Basic |
--oauth2-bearer | Bearer token | Authorization tab set to Bearer |
-b, --cookie | Sends cookies | Cookie header (a cookie file is reported, not read) |
-A, -e | User-Agent, Referer | Matching headers |
-G, --get | Puts -d data in the query string | Data appended to the URL |
-I, --head | HEAD request | Method HEAD |
-k, --insecure | Skips TLS certificate verification | Turns off Enable SSL certificate verification for the request |
-L, --location | Follows redirects (curl does not by default) | Redirects are followed (the app's default) |
-m, --max-time | Overall time limit in seconds | Request timeout |
--max-redirs | Redirect limit | Maximum redirects setting |
--compressed | Asks for a compressed response and decompresses it | Accepted; the engine already sends Accept-Encoding and decompresses |
In the import dialog, --digest and --ntlm next to -u set the auth type to Digest or NTLM, and --http2 or --http1.1 set the request's HTTP version. Output-only flags such as -s, -v, -i, -o and -w are ignored because they only affect how curl prints.
File references need attention: the web app cannot read a path on your disk, so check file fields in the Body tab and select the file there before sending.
Step 3: generate Python, JavaScript or other code
With the request open, click the Code snippet button in the request toolbar (or run Generate code snippet from the command palette). Choose a language and copy or download the snippet. The 30 targets are:
| Language | Targets |
|---|---|
| Shell | cURL, Wget, HTTPie, PowerShell (Invoke-RestMethod) |
| Raw | HTTP request text |
| JavaScript | Fetch, Axios, jQuery, XHR |
| Node.js | native http, Axios |
| Python | Requests, http.client |
| Go | net/http |
| Java | OkHttp, Unirest, java.net.http |
| C# | HttpClient, RestSharp |
| PHP | cURL, Guzzle |
| Ruby | Net::HTTP |
| Swift | URLSession |
| Kotlin | OkHttp |
| Dart | http |
| Rust | reqwest |
| C | libcurl |
| R | httr, RCurl |
| OCaml | Cohttp |
Two options matter:
- Resolve variables: on,
{{baseUrl}}and{{token}}are replaced with their current values; off, the placeholders stay. Resolved snippets can contain real secrets. - Snippet settings: indent with spaces or tabs, the indent width, and whether to trim the request body.
The request's auth is applied in the snippet, including auth inherited from a folder or collection, so a Bearer token becomes an Authorization header. Generating code never sends the request. The code generation page has the details.
The round trip also works the other way: build or fix a request in the app, then pick cURL as the target to get a command for a terminal or a bug report.
Converting by hand: cURL to Python requests and fetch
If you only need one conversion, or want to understand what a generator produces, these are the equivalents for the common flags.
Method, headers and a JSON body (-X, -H, --data-raw)
curl -X POST https://api.example.com/v1/orders \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer abc123' \
--data-raw '{"sku":"A-1","quantity":2}'import requests
resp = requests.post(
"https://api.example.com/v1/orders",
headers={"Authorization": "Bearer abc123"},
json={"sku": "A-1", "quantity": 2}, # json= sets Content-Type: application/json
)
print(resp.status_code, resp.json())const resp = await fetch('https://api.example.com/v1/orders', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer abc123',
},
body: JSON.stringify({ sku: 'A-1', quantity: 2 }),
});
console.log(resp.status, await resp.json());Form data (-d)
curl -d 'name=Ada&role=admin' https://api.example.com/users sends application/x-www-form-urlencoded and uses POST because data is present.
requests.post("https://api.example.com/users", data={"name": "Ada", "role": "admin"})await fetch('https://api.example.com/users', {
method: 'POST',
body: new URLSearchParams({ name: 'Ada', role: 'admin' }), // sets the form content type
});Basic auth (-u)
curl -u ada:secret https://api.example.com/me sends Authorization: Basic with ada:secret Base64-encoded.
requests.get("https://api.example.com/me", auth=("ada", "secret"))// Browser: btoa(); in Node.js use Buffer.from('ada:secret').toString('base64')
await fetch('https://api.example.com/me', {
headers: { Authorization: 'Basic ' + btoa('ada:secret') },
});File upload (-F)
curl -F 'title=Report' -F 'file=@report.pdf' https://api.example.com/upload sends multipart/form-data.
with open("report.pdf", "rb") as f:
requests.post(
"https://api.example.com/upload",
data={"title": "Report"},
files={"file": ("report.pdf", f, "application/pdf")},
)const form = new FormData();
form.append('title', 'Report');
form.append('file', fileInput.files[0]); // a File or Blob
await fetch('https://api.example.com/upload', { method: 'POST', body: form });
// Do not set Content-Type yourself: the multipart boundary is added for you.Insecure TLS (-k)
requests.get("https://dev.internal/health", verify=False) # or verify="/path/to/ca.pem"fetch in a browser has no equivalent; the browser decides whether to trust a certificate. In Node.js you can pass a custom dispatcher from the undici package with connect: { rejectUnauthorized: false }. In every language, prefer trusting the specific CA over turning verification off.
Redirects (-L) and compression (--compressed)
curl does not follow redirects unless you pass -L. Python requests follows them by default (set allow_redirects=False to stop), and fetch follows them by default (redirect: 'manual' or 'error' to change that). Both libraries request compressed responses and decompress them automatically, so --compressed usually needs no translation.
Common conversion mistakes
- Dropping the method change.
-dor-Fwithout-Xstill means POST. A converted GET with a body is a frequent bug. - Sending JSON as form data.
-d '{"a":1}'without aContent-Type: application/jsonheader is sent asapplication/x-www-form-urlencodedby curl. Many servers then reject it; add the header (or use--json) in the original command too. - Setting the multipart Content-Type by hand. The boundary must match the body, so let the library generate the header.
- Quoting on Windows. Single quotes do not work in
cmd. Use the browser's cmd variant or paste into the import dialog, which handles^escapes. - Leaking tokens. Generated snippets with resolved variables, and commands copied from devtools, contain live credentials. Rotate anything that ends up somewhere public.
Frequently asked questions
How do I convert a cURL command to Python requests?
Paste the command into a Swastik Codes request (URL bar or import dialog), open the Code snippet panel and choose Python - Requests. By hand: -X becomes the method function, -H the headers dict, -d the data argument (or json for JSON), -u the auth tuple, -F the files argument and -k verify=False.
How do I convert cURL to JavaScript fetch?
Import the command, then choose JavaScript - Fetch in the code snippet panel. By hand, -X maps to method, -H to headers, -d to body (a string, URLSearchParams or FormData), and Basic auth to an Authorization header you build yourself.
What is the difference between -d, --data-raw and --data-binary?
-d treats a leading @ as a file name and strips newlines from file contents. --data-raw sends the value as typed, even if it starts with @. --data-binary sends data exactly as given, including newlines, which matters for uploads.
Can I import several cURL commands at once?
Yes. Paste them together into the import dialog and each command becomes a request in one new collection.
Does Swastik Codes convert requests back to cURL?
Yes. Choose cURL in the code snippet panel. Other shell targets are Wget, HTTPie and PowerShell.
Is my cURL command sent anywhere when I convert it?
The import dialog parses the text with Swastik Codes' own importer (in the web app on the swastik.codes server, with an in-browser fallback; in the desktop app locally). The API named in the command is not called. Generating code never sends the request. Only pressing Send calls the API.