Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
API

Convert cURL Commands to Python Requests (with Complete Examples)

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To convert a cURL command to Python, preserve its HTTP method, URL, query string, headers, cookies, authentication, body, file uploads, redirects, TLS settings and timeout. For ordinary requests, Python’s requests library maps these parts directly: use params= for query parameters, headers= for headers, cookies= for cookies, data= for form or raw data, json= for JSON objects, files= for multipart uploads and auth= for Basic authentication.

Install Requests and read the cURL command completely

The examples below use Requests 2.34.2 documentation, which identifies Python 3.10+ as officially supported. Check the current project documentation if your environment uses a newer release. Install it with:

python -m pip install requests

Do not translate only the URL. Before writing Python, identify every meaningful cURL option:

  • Method: GET, POST, PUT, PATCH, DELETE or another method.
  • URL and query parameters, including repeated parameters.
  • Headers such as Authorization, Accept and Content-Type.
  • Cookies, form fields, JSON, raw bytes or uploaded files.
  • Authentication, redirects, proxies, compression, TLS verification and certificates.
  • Output behavior: whether cURL writes a response body to a file, prints headers or follows redirects.

Shell quoting and variable expansion also matter. A quoted JSON string, an environment variable and a local file reference each require a different Python representation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Basic GET: the direct conversion

cURL:

curl https://api.example.com/users

Python:

import requests

response = requests.get("https://api.example.com/users", timeout=30)
response.raise_for_status()
print(response.text)

raise_for_status() makes HTTP 4xx and 5xx responses visible. Without it, a request can complete at the transport level while the server has rejected it.

Save binary output instead of printing it

import requests

response = requests.get("https://example.com/archive.zip", timeout=60)
response.raise_for_status()
with open("archive.zip", "wb") as output:
    output.write(response.content)

Use response.content for bytes and response.text for decoded text. For a JSON response, call response.json() only after checking the status.

Map methods, parameters and headers

cURL intent Requests equivalent
GET requests.get(url, ...)
POST, PUT, PATCH or DELETE The matching convenience method, or requests.request("METHOD", url, ...)
?page=2&limit=20 params={"page": 2, "limit": 20}
-H "Name: value" headers={"Name": "value"}
-b "session=abc" cookies={"session": "abc"}
-u user:password auth=("user", "password")

Query parameters

Keep the base URL separate from parameters so Requests performs URL encoding:

import requests

params = {"q": "red shoes", "page": 2, "tag": ["sale", "new"]}
response = requests.get(
    "https://api.example.com/search",
    params=params,
    timeout=30,
)
response.raise_for_status()
print(response.url)
print(response.json())

Print response.url while verifying a conversion. It shows the encoded URL that was actually sent. For repeated keys, a list value is appropriate; confirm that the destination API accepts the resulting representation.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Headers

import requests

headers = {
    "Accept": "application/json",
    "Authorization": "Bearer YOUR_TOKEN",
}
response = requests.get(
    "https://api.example.com/profile",
    headers=headers,
    timeout=30,
)
response.raise_for_status()

Do not hard-code real credentials in source control. Read secrets from environment variables or your secret manager. Header names are case-insensitive, but values and spacing are not always interchangeable.

POST bodies: form data, JSON and raw content

Form-encoded fields

For cURL form fields such as -d "name=Sam" -d "role=admin", use data=:

import requests

response = requests.post(
    "https://api.example.com/users",
    data={"name": "Sam", "role": "admin"},
    timeout=30,
)
response.raise_for_status()
print(response.json())

JSON objects

Use json= when the request body is a Python dictionary or list that should be encoded as JSON:

import requests

payload = {"name": "Sam", "roles": ["admin"]}
response = requests.post(
    "https://api.example.com/users",
    json=payload,
    timeout=30,
)
response.raise_for_status()
print(response.json())

Requests’ json= argument encodes the object and sets the appropriate JSON content type. Passing a serialized string through data= does not automatically add Content-Type: application/json. Also, json= is ignored when data= or files= is supplied; do not combine them expecting two bodies.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Raw or pre-serialized data

If the cURL command sends exact bytes, preserve them explicitly and copy any required content type:

import requests

raw_body = '{"name":"Sam"}'
response = requests.post(
    "https://api.example.com/users",
    data=raw_body,
    headers={"Content-Type": "application/json"},
    timeout=30,
)
response.raise_for_status()

This is useful when the server requires a specific serialization, signature or byte sequence.

Multipart uploads and file fields

Translate cURL’s multipart options (for example, -F "[email protected]") with files=. Let Requests generate the multipart boundary; manually setting it is a common source of broken uploads.

import requests

with open("report.pdf", "rb") as document:
    response = requests.post(
        "https://api.example.com/upload",
        files={"file": document},
        data={"description": "Monthly report"},
        timeout=120,
    )
response.raise_for_status()
print(response.json())

You can provide a tuple containing filename, file object or bytes, content type and per-part headers:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
files = {
    "file": (
        "report.pdf",
        open("report.pdf", "rb"),
        "application/pdf",
        {"Expires": "0"},
    )
}

Close file handles with a context manager when the request finishes.

Authentication, cookies and sessions

Basic authentication

import requests

response = requests.get(
    "https://api.example.com/private",
    auth=("username", "password"),
    timeout=30,
)
response.raise_for_status()

Requests can also consult a netrc file when explicit authentication is not supplied. If the cURL command constructs an unusual authentication header, reproduce that header exactly instead of assuming Basic authentication.

Bearer tokens and API keys

import os
import requests

token = os.environ["API_TOKEN"]
response = requests.get(
    "https://api.example.com/data",
    headers={"Authorization": f"Bearer {token}"},
    timeout=30,
)
response.raise_for_status()

Cookies and persistent sessions

import requests

with requests.Session() as session:
    session.headers.update({"Accept": "application/json"})
    session.cookies.update({"session": "abc123"})
    first = session.get("https://api.example.com/login-check", timeout=30)
    first.raise_for_status()
    second = session.get("https://api.example.com/account", timeout=30)
    second.raise_for_status()
    print(second.json())

A session reuses connections and carries cookies between requests, which is closer to a sequence of cURL commands that shares a cookie jar.

Redirects, TLS, proxies and other cURL flags

Common flags do not always have identical defaults. Review the original command rather than assuming a convenience method is equivalent.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Redirects: Requests follows redirects by default for most methods. Set allow_redirects=False when the cURL command does not follow them, or inspect response.history to audit the chain.
  • TLS verification: Keep certificate verification enabled. Use verify="/path/to/ca-bundle.pem" for a custom CA. Disabling verification with verify=False weakens transport security and should not be a routine conversion.
  • Client certificates: Use cert="/path/client.pem" or a (certificate, key) tuple where the cURL command supplies a client certificate.
  • Proxies: Configure the proxies= argument or the relevant environment variables, matching the cURL runtime environment.
  • Compression and streaming: Requests handles normal response decompression. For large downloads, use stream=True and iterate over chunks rather than loading the entire body into memory.
  • Output and headers: cURL options that print response headers, discard the body or write to a file require corresponding Python handling; they are not part of the HTTP request itself.

cURL does not forward Authorization and Cookie headers to a different origin after a redirect by default. Check the destination and Requests’ redirect behavior before assuming credentials follow every hop.

One reusable conversion pattern

For a request whose method and options may vary, use requests.request():

import requests

response = requests.request(
    method="PATCH",
    url="https://api.example.com/items/42",
    params={"notify": "true"},
    headers={
        "Accept": "application/json",
        "Authorization": "Bearer YOUR_TOKEN",
    },
    json={"status": "ready"},
    timeout=(10, 60),
    allow_redirects=False,
)
print("status:", response.status_code)
response.raise_for_status()
print(response.json())

The two-value timeout sets separate connection and read limits. Choose values appropriate for the endpoint instead of allowing a request to wait indefinitely.

Verify that the Python request still means the same thing

  1. Compare the HTTP method and final URL, including encoded query parameters.
  2. Compare outgoing headers, but remove secrets before logging.
  3. Confirm whether the body is form encoded, JSON, multipart or raw bytes.
  4. Check cookies, authentication, redirect policy, proxy settings and TLS verification.
  5. Run against a safe test endpoint or environment, then inspect response.status_code, selected response headers and the body.
  6. Use response.json() only when the endpoint returns JSON; valid JSON can still be an error response, so status checking remains separate.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting conversion failures

415 Unsupported Media Type

The server expected a different body encoding or content type. Replace data= with json= for a JSON object, or set the exact content type when sending raw data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

422 or 400 validation errors

Inspect the serialized body and parameter names. A cURL command using repeated -d fields, nested JSON or array parameters may not map to the dictionary shape you chose.

401 or 403 responses

Check the authentication scheme, token prefix, cookies, header spelling and redirect destination. Do not assume a token sent to one origin is valid after a cross-origin redirect.

Multipart upload rejected

Use files=, keep the file open during the request and avoid manually setting the multipart boundary. Include ordinary fields in data=.

Timeouts or hanging requests

Set a connect/read timeout, verify DNS and proxy configuration, and use streaming for large responses. A longer timeout does not fix an incorrect URL or server-side failure.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

SSL certificate errors

Install or reference the correct CA bundle with verify=. Treat verify=False as a diagnostic exception, not a production solution.

Different results after a redirect

Log response.url and inspect response.history. Compare how cURL and Requests handle credentials, cookies and method changes across each redirect.

Or skip the browser setup

If the cURL command you are converting is for a website screenshot, ScreenshotNeo provides a direct HTTP endpoint instead of requiring you to configure a headless browser. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.

One call in cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The equivalent Python request is:

import requests

r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

See the parameter reference and additional options in the ScreenshotNeo documentation. Its API also supports full-page and element captures, device presets, dark mode, custom CSS and JavaScript, waits, request blocking, cookies, headers, PDFs, signed links, asynchronous jobs, bulk capture and a usage API. An MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Performance, reliability and cost considerations

  • Reuse a Session for related requests to reduce connection setup.
  • Set finite connect and read timeouts and handle transient failures at the application layer.
  • Stream large downloads and write chunks to disk.
  • Do not automatically retry non-idempotent POST requests unless the API documents safe retry behavior or you use an idempotency key.
  • Log status, elapsed time, final URL and a request identifier, but redact authorization headers, cookies and personal data.
  • Keep the same proxy, CA bundle, DNS context and environment variables used by the original cURL invocation when comparing behavior.

Requests is a convenient documented option for common HTTP features. The available evidence does not establish an empirical performance ranking against other Python HTTP clients, so choose another client only when your project needs capabilities Requests does not provide.

Frequently Asked Questions

Can an automated converter translate every cURL flag perfectly?

No. cURL has options for transport, TLS, redirects, proxies, uploads and command-line output that may require manual decisions in Python. Review the complete command and verify the resulting request.

Should I use data= or json= in Requests?

Use json= for a Python object that the server expects as JSON. Use data= for form-encoded fields or exact raw content, adding the required content type yourself for serialized JSON.

Why does response.json() not prove that the request succeeded?

A server can return a valid JSON error document with an HTTP 4xx or 5xx status. Check response.status_code or call raise_for_status() before treating the response as successful.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do I preserve a cURL file upload?

Open the file in binary mode and pass it through files=. Put ordinary multipart fields in data= and let Requests create the multipart boundary.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.