Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Requests’ json= parameter: pass a Python dictionary, list, or other JSON-serializable object directly to requests.post(). Requests serializes it and applies the JSON request workflow for you.
import requests
url = "https://api.example.com/items"
payload = {"name": "Alice", "active": True}
response = requests.post(url, json=payload, timeout=10)
response.raise_for_status()
result = response.json()
print(result)
This pattern avoids the most common mistakes: manually encoding JSON, sending the wrong Content-Type, waiting forever for a server, or parsing an error response as if it were success.
The recommended way to post JSON
For a JSON API, put your Python object in json=payload and provide a finite timeout. Requests handles serialization and the JSON content workflow.
Free tools Windows power users keep installed
One-click scans. No signup required.
import requests
url = "https://api.example.com/items"
payload = {
"name": "Alice",
"active": True,
"tags": ["new", "priority"]
}
response = requests.post(
url,
json=payload,
timeout=10
)
response.raise_for_status()
result = response.json()
print(result)
The payload can contain nested dictionaries, lists, strings, numbers, booleans, and None values that are valid JSON equivalents. The Requests API describes json as a JSON-serializable Python object sent in the request body.
#1 Best Overall
Why json= is preferable
- You pass Python data rather than maintaining a separate JSON string.
- Requests performs the serialization step.
- The request uses the JSON content workflow instead of dictionary form encoding.
- Your code remains easy to read and change as the payload grows.
Requests documentation currently identifies release 2.34.2 and officially supports Python 3.10 and newer. Check the installed version in the same environment where your script runs if behavior differs from your deployment.
json= versus data= and files=
These parameters represent different body formats. Choose one deliberately.
| Goal | Requests call | What is sent |
|---|---|---|
| JSON API body | requests.post(url, json=payload) |
Requests serializes the object using its JSON workflow. |
| Form submission | requests.post(url, data=form_data) |
A dictionary is form-encoded. |
| Multipart upload | requests.post(url, files=files) |
Files are encoded as multipart data. |
| Already serialized body | requests.post(url, data=json_text) |
You control the serialized text and headers. |
The parameter interaction that causes silent mistakes
The json parameter is ignored when either data or files is supplied. Do not pass a payload through both mechanisms and assume Requests will merge them. Decide whether the endpoint expects JSON, a form, or multipart data, then use only the matching argument.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsWhen data= is appropriate
Use data= for a traditional form post:
import requests
form_data = {
"username": "alice",
"newsletter": "yes"
}
response = requests.post(
"https://api.example.com/signup",
data=form_data,
timeout=10
)
response.raise_for_status()
If you intentionally pre-serialize JSON, data= can carry the resulting string, but you must manage the header yourself:
import json
import requests
payload = {"name": "Alice", "active": True}
json_text = json.dumps(payload)
response = requests.post(
"https://api.example.com/items",
data=json_text,
headers={"Content-Type": "application/json"},
timeout=10
)
response.raise_for_status()
The Requests Quickstart specifically warns that the manual data=json.dumps(...) form does not add Content-Type: application/json automatically. Omitting that header can lead to a server response such as “unsupported media type” even though the body is valid JSON.
Rank #2
Headers, authentication, and a production-ready function
Many APIs require authentication or an explicit Accept header. Add those headers while still using json=; do not switch to manual serialization merely because the request needs headers.
import requests
def create_item(token: str, name: str) -> dict:
response = requests.post(
"https://api.example.com/items",
json={"name": name, "active": True},
headers={
"Authorization": f"Bearer {token}",
"Accept": "application/json"
},
timeout=10
)
response.raise_for_status()
return response.json()
item = create_item("YOUR_TOKEN", "Alice")
print(item)
Keep secrets out of source control and logs. Store the token in your runtime’s secret manager or environment configuration, then pass it to the function.
Check HTTP success before decoding JSON
Posting data and receiving a response are separate from proving that the operation succeeded. A server may return a JSON error document with an unsuccessful HTTP status. Call raise_for_status() before treating the response as a successful result.
response = requests.post(
"https://api.example.com/items",
json={"name": "Alice"},
timeout=10
)
print(response.status_code)
response.raise_for_status()
result = response.json()
raise_for_status() raises an HTTP error for unsuccessful status codes. If you need custom handling instead, inspect response.status_code explicitly:
if 200 <= response.status_code < 300:
print("HTTP request succeeded")
else:
print("HTTP request failed:", response.status_code)
print(response.text)
Do not infer success solely from the presence of a JSON object. The status code is the transport-level result; the response fields still need to satisfy your application’s business rules.
Parse response JSON defensively
response.json() decodes the response body, but it cannot decode every response. Invalid JSON raises requests.exceptions.JSONDecodeError; a 204 No Content response also has nothing to decode.
Handle an empty successful response
response = requests.post(
"https://api.example.com/items",
json={"name": "Alice"},
timeout=10
)
response.raise_for_status()
if response.status_code == 204 or not response.content:
result = None
else:
result = response.json()
print(result)
Handle a non-JSON success response
response = requests.post(
"https://api.example.com/items",
json={"name": "Alice"},
timeout=10
)
response.raise_for_status()
try:
result = response.json()
except requests.exceptions.JSONDecodeError:
result = response.text
print(result)
Use the response’s documented media type and status behavior when deciding whether to parse JSON. Do not hide a parsing failure by catching every exception indiscriminately.
Timeouts are part of the request design
Always set a finite timeout for production calls. Without one, a stalled connection can leave a worker waiting indefinitely. The timeout belongs on the request itself:
response = requests.post(
"https://api.example.com/items",
json={"name": "Alice"},
timeout=10
)
Choose a value appropriate to the API and your application’s latency budget. A short interactive request and a long-running data import may need different limits. A timeout means your client stopped waiting; it does not prove that the server did not receive or process the request. Be careful about automatically repeating non-idempotent POST operations unless the API provides an idempotency mechanism.
Complete examples in Python, cURL, and Node.js
Python Requests
import requests
payload = {
"name": "Alice",
"active": True
}
response = requests.post(
"https://api.example.com/items",
json=payload,
headers={"Accept": "application/json"},
timeout=10
)
response.raise_for_status()
if response.status_code == 204 or not response.content:
print("Created; no response body")
else:
print(response.json())
cURL equivalent
curl --request POST "https://api.example.com/items"
--header "Content-Type: application/json"
--header "Accept: application/json"
--data '{"name":"Alice","active":true}'
Node.js fetch equivalent
const payload = { name: "Alice", active: true };
const response = await fetch("https://api.example.com/items", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
const text = await response.text();
const result = text ? JSON.parse(text) : null;
console.log(result);
Unlike Requests’ json= convenience argument, the JavaScript example explicitly calls JSON.stringify() and sets the content type.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Troubleshooting common failures
400 Bad Request
The server received the request but rejected its contents. Compare field names, required values, data types, and nesting with the API contract. Print the response body after catching the HTTP error; many APIs put the exact validation message there.
401 Unauthorized or 403 Forbidden
Check the token, authorization scheme, required scopes, and whether the credential is being sent to the intended host. Avoid printing the full authorization header while debugging.
415 Unsupported Media Type
The endpoint does not recognize the body’s media type. For JSON, prefer json=payload. If you used data=json.dumps(payload), add Content-Type: application/json yourself.
The server says the body is form data
You probably passed a dictionary to data=. Change it to json=payload when the endpoint expects JSON. Also verify that no data or files argument is causing Requests to ignore json.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
JSONDecodeError after a successful status
The response may be empty, plain text, HTML, or malformed JSON. Check response.status_code, response.headers, and response.text before calling response.json(). Treat 204 as an intentional no-body response.
Best Value
Timeout
Confirm the URL, DNS, network access, proxy settings, and server health. Increase the timeout only when the endpoint legitimately needs more time. Do not remove the timeout as a workaround.
My JSON contains a value Python cannot serialize
The object passed to json= must be JSON serializable. Convert application-specific objects, such as custom classes or date types, to strings, numbers, dictionaries, or lists before sending them.
Or skip the browser setup
If the next step in your workflow is capturing a web page or API documentation rather than posting data to an API, ScreenshotNeo provides a single-call screenshot API. It removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and each response identifies the page verdict and billing status in headers. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.
See the ScreenshotNeo API documentation for all options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
There is a free plan with 1,000 screenshots per month and no card required. Paid plans start at $5 for 3,000 screenshots; every feature is included on every plan. Create a free ScreenshotNeo account to begin.
Bottom line
For a JSON API, use requests.post(url, json=payload, timeout=...), call raise_for_status(), and parse the body only when the response actually contains JSON. Reserve data= for forms or deliberately pre-serialized content, and remember that json is ignored whenever data or files is supplied.
Frequently Asked Questions
Does raise_for_status() read the API’s error message?
No. It evaluates the HTTP status and raises an exception for an unsuccessful response. Inspect the exception’s response, or log the response body separately, when you need the API’s validation details.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCan a POST return success without a JSON object?
Yes. An API can legitimately return 204 No Content or another non-JSON body. Check the status and body length before calling response.json().
What is the safest value to use for a timeout?
There is no universal number. Set a finite value that fits the endpoint’s expected latency and your application’s deadline, then handle timeout failures explicitly.
Quick Recap
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.

