Why developers keep converting curl to Python
Right-click a request in browser DevTools, choose "Copy as cURL", and you get a complete command: URL, headers, body, cookies — everything. The next step is usually reproducing that request in Python: scrapers, API clients, automation checks. The mapping itself is mechanical, but with many flags it's easy to miss one — drop an -H and you get a 401; drop --data-raw and the method silently becomes GET.
Mechanical translation is exactly what tools are for: the curl command converter takes the pasted command, generates requests code instantly when you pick the Python target, and can send it straight into the online Python runner to execute.
The mapping, flag by flag
Start with a typical command:
curl 'https://api.example.com/v1/users' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer demo-token' \
--data-raw '{"name":"Ada","role":"admin"}'
The converted Python:
import requests
url = "https://api.example.com/v1/users"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer demo-token",
}
data = '{"name":"Ada","role":"admin"}'
response = requests.post(url, headers=headers, data=data, allow_redirects=False)
print(response.status_code)
print(response.text)
Where each flag lands:
| curl form | requests landing spot | Notes |
|---|---|---|
| URL (first argument) | url |
quoting preserved |
-H 'name: value' |
one entry in the headers dict |
later duplicates override earlier |
-d / --data-raw |
data string |
multiple -d joined with & |
-X POST |
requests.post |
inferred as POST when -d present, no -X |
-u user:pass |
auth=(user, pass) |
or hand-write the Authorization Basic header |
-b 'k=v' |
Cookie header in headers |
prefer Session for sessions |
-G |
data moves into the query string | method falls back to GET |
-k |
verify=False |
test environments only |
-L |
default (omit allow_redirects=False) | curl defaults to not following; requests follows |
-A 'UA/1.0' / -e 'url' |
User-Agent / Referer headers | curl semantics are just header sets |
One trap worth knowing: when curl has a body but no Content-Type, it sends application/x-www-form-urlencoded by default. A good converter adds that header for you (curlconverter.com and this site's tool both do); otherwise servers may parse the body as raw text and return 400.
JSON requests: choosing between data and json
Converting --data-raw '{"name":"Ada"}' yields the string form. To use the json parameter, parse it into a dict first:
import json
payload = {"name": "Ada", "role": "admin"}
response = requests.post(url, headers=headers, json=payload)
json=payload serializes automatically and sets Content-Type: application/json. Both forms behave identically on the wire — pick by team convention: the string form means smaller diffs while tweaking payloads; the dict form reads better in business code.
Cookies and login state: Session is the answer
curl's -b 'session=xyz' converts to a single Cookie header — fine for one request. But once you hit more endpoints on the same site, hand-managing cookies falls apart. requests' Session catches Set-Cookie automatically:
session = requests.Session()
session.headers.update({"User-Agent": "MyApp/1.0"})
login = session.post("https://api.example.com/login", data={"user": "ada", "pass": "***"})
profile = session.get("https://api.example.com/me") # login state carried over
The typical scraper pipeline: copy the login request from DevTools → convert to Python → switch to Session → loop the pages. Every step's mapping is in the table above.
How to pick a converter
Three practical criteria:
- Flag coverage: -H/-d/--data-raw/--json/-u/-b/-G/-L/-k plus combined shorts (-sSL) and multi-line continuations are the high-frequency set; missing any one means manual patching.
- Error feedback: when a command fails to parse, a tool that points at the offending flag halves your debugging time; one that only says "parse error" is a tier below.
- What happens after conversion: can the generated code run immediately? The curl converter on this site sends its Python output straight into the online runner (requests built in), so you see the status code and body on the spot; Go and Java targets work the same way, while PHP and C++ are copy-only.
Frequently Asked Questions
How do I convert a curl command into Python requests code?
Map it in three steps: the URL becomes the first argument; each -H "name: value" goes into the headers dict; the -d/--data-raw content becomes the data string, with requests.post as the method (curl with -d and no -X is a POST). An online converter skips the manual work: paste the command, pick Python, and the code generates instantly — and can be sent straight into an online runner to verify.
Should I use data or json when converting a curl JSON request to Python?
Both send JSON. With data you must ensure the string is valid JSON and set the Content-Type: application/json header yourself; with json you pass a dict and requests serializes and sets the header automatically. Converting from curl -d or --json yields the string form first — confirm the structure, then switch to the json parameter.
What do curl's -b and -u become in Python?
-b "name=value" becomes a Cookie request header; for cookie-backed sessions, switch to requests.Session() to persist login state. -u user:pass maps to auth=("user", "pass"), which requests turns into an Authorization Basic header — no manual Base64 needed.
Why does the converted Python code fail with 'No module named requests'?
requests is a third-party library — run pip install requests first. Online runtimes (like this site's Python runner) ship with requests built in, so pasting the generated code there runs immediately: handy for verifying logic before moving it into a local project.