Pass a dictionary with headers= to set headers on one Requests call. Put defaults used across calls on a requests.Session, then use response.request.headers to inspect the outgoing headers Requests prepared. A Session combines its defaults with per-request settings, but authentication, redirects, proxy credentials, and body preparation can change some values. This guide follows the Requests project’s 2026 documentation snapshot, which identifies Requests 2.34.2 and Python 3.10+ as the supported baseline.
Set headers on a single request
Pass a dictionary as the headers argument to a top-level request function such as requests.get() or requests.post(). This is the simplest choice when the value applies to just one call.
import requests
url = "https://api.example.com/items"
headers = {
"Accept": "application/json",
"User-Agent": "inventory-client/1.0",
}
response = requests.get(url, headers=headers, timeout=(3.05, 20))
response.raise_for_status()
print(response.json())
The Accept header tells the server which response format the client can handle; User-Agent identifies the client. Those meanings come from HTTP conventions, not special Requests behavior: Requests passes custom header names through to the request, subject to its documented precedence rules. Header values should be strings, bytestrings, or values compatible with Unicode.
Always choose an explicit timeout for network calls. The tuple in this example sets a 3.05-second connection timeout and a 20-second read timeout. Requests otherwise has no default timeout, so a call can wait indefinitely if the server does not respond.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
Set headers on a request with a body
For JSON APIs, use json= to send a JSON body and set an appropriate content type if your endpoint requires it. For example:
payload = {"name": "sample"}
response = requests.post(
"https://api.example.com/items",
json=payload,
headers={"Accept": "application/json"},
timeout=(3.05, 20),
)
response.raise_for_status()
Requests prepares body-related details as part of creating the request. In particular, do not assume that a manually supplied Content-Length will remain unchanged; Requests may calculate and replace it when it can determine the body length.
Reuse defaults with a Session
Use a requests.Session when several calls share stable defaults. A Session also persists cookies and uses automatic keep-alive and connection pooling, which avoids treating every call as an entirely separate client interaction.
import requests
session = requests.Session()
session.headers.update({
"Accept": "application/json",
"User-Agent": "inventory-client/1.0",
})
first = session.get(
"https://api.example.com/items",
timeout=20,
)
first.raise_for_status()
second = session.get(
"https://api.example.com/items/42",
headers={"X-Request-ID": "abc-123"},
timeout=20,
)
second.raise_for_status()
The session-level headers apply across calls made through that Session. A per-request header mapping supplies an endpoint-specific value and is combined with the Session settings; when both specify the same header, the per-request setting is the one to use for that call. In the example, the second request retains the Session’s Accept and User-Agent while adding its request ID.
Rank #2
Choose the right scope for each value
- One-off header: pass it in that call’s
headers=mapping. - Stable default across endpoints: add it to
session.headers. - Endpoint-specific override: pass the replacement value in the request’s own
headers=mapping. - Short-lived secret or host-specific value: avoid making it a default on a Session shared across unrelated hosts. Keep credentials narrowly scoped.
This division makes it easier to understand where a value came from. It also reduces the chance that an endpoint-specific content type or bearer token will unintentionally travel with unrelated calls.
Inspect outgoing and response headers
After a call, response.request is the PreparedRequest that Requests used. Its headers mapping is the place to inspect what Requests prepared to send. By contrast, response.headers contains headers received from the server.
response = session.get(
"https://api.example.com/items",
timeout=20,
)
sent_headers = dict(response.request.headers)
received_headers = dict(response.headers)
print("Prepared request headers:", sent_headers)
print("Response headers:", received_headers)
Do not mix up these two directions when debugging. If an API says a request header is missing, inspect response.request.headers; looking at response.headers only tells you what the server returned.
Requests uses a case-insensitive header mapping, so header lookup is not dependent on whether you spell a name as Content-Type, content-type, or another casing. The prepared request represents the request after Requests has applied the session and request configuration, making it more useful for debugging than the dictionary you started with.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated 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 matchPrepare and inspect a request before sending
If you need to see the prepared values before network I/O, build a Request and prepare it through the Session. Preparing through the Session applies its headers and other session state.
from requests import Request, Session
session = Session()
session.headers.update({"Accept": "application/json"})
request = Request(
"GET",
"https://api.example.com/items",
headers={"X-Debug": "1"},
)
prepared = session.prepare_request(request)
print(dict(prepared.headers))
response = session.send(prepared, timeout=20)
response.raise_for_status()
Use this when the problem concerns the final prepared header set rather than the values in your input mapping. A PreparedRequest is mutable and represents the request Requests is about to send. For ordinary calls, inspecting response.request.headers after the response is usually simpler; prepare explicitly when you need to examine the request before sending it.
Why Requests can replace or remove a header
A header dictionary is not always the final authority. Requests has documented precedence and preparation behavior that can account for a missing or unexpected value.
| Header or situation | What can happen | What to check |
|---|---|---|
Authorization |
Credentials from .netrc can override an Authorization value passed in headers=; the auth= parameter has higher precedence as well. |
Check whether the call uses auth= and whether applicable .netrc credentials are configured. |
| Redirect to another host | Requests removes Authorization when a redirect moves off-host. | Inspect the final response and the prepared request used for the relevant destination; consider whether following that redirect is appropriate. |
Proxy-Authorization |
Proxy credentials in the proxy URL can override a value supplied as a header. | Check the configured proxy URL and credentials. |
Content-Length |
Requests may replace a supplied value when it can determine the body length. | Check the body actually being sent and inspect the prepared headers rather than relying on the original dictionary. |
When a value differs from what you set, debug at the prepared-request level after authentication, redirect, proxy, and body preparation have run. This narrows the search to the configuration stage that can affect that header.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Troubleshoot common header problems
The API says a header is missing
- Check that the header was passed as a mapping to the correct call’s
headers=argument, or added to the Session actually making the call. - Inspect
response.request.headers, or callsession.prepare_request()and inspect the prepared mapping before sending. - If the header is an authorization or body-related header, compare it with the precedence cases above. The original dictionary does not establish the final value.
The server receives an unexpected Authorization value
Check .netrc credentials and the auth= argument first. Then consider whether the request was redirected to another host, where Requests removes Authorization. Avoid sharing one Session containing a short-lived token across unrelated hosts.
Content-Length does not match the value I set
Requests may calculate this header from the body when it knows its length. Inspect the prepared request and confirm that the body itself is what you intended to send. Usually the reliable fix is to provide the correct body and let Requests prepare its length, rather than trying to force a stale length value.
The request appears to hang
Set a timeout on each network call. Use a single number for the timeout value or a pair for connection and read timeouts, as in the examples. Requests does not impose a timeout automatically.
My debug output contains secrets
Outgoing request headers can include bearer tokens, cookies, API keys, or other credentials. Redact those values before printing, storing, or sharing a header dump. Inspection is useful for debugging, but raw logs can expose credentials.
Best Value
Performance, reliability, and cost considerations
A Session is the practical choice for repeated requests to an API because it retains cookies and uses keep-alive and connection pooling automatically. That is a transport capability, not a guarantee that every API call will be faster: the server, network, and request workload still affect elapsed time. Reuse a Session where its shared state is appropriate, and set a timeout even when pooling is enabled.
Requests itself does not define the price of the API you call. Check that API’s own billing rules, rate limits, and authentication guidance. For reliability, make the timeout deliberate and treat HTTP errors explicitly with raise_for_status() or your application’s equivalent error handling instead of assuming a successful response.
Or skip the browser setup
Requests is for making HTTP calls; it does not render a page like a browser. If your goal is a website screenshot or PDF rather than inspecting HTTP headers, ScreenshotNeo is a website screenshot API and MCP server. Its one-call API can return an image or PDF, with options including PNG, JPEG, or WebP output.
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
See the ScreenshotNeo documentation for request options and response details. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; each of those steps can be turned off. Bot checks, blank pages, and failed loads are not billed, and the response indicates the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo’s free plan.
Frequently Asked Questions
Does the casing of a header name matter in Requests?
Requests uses a case-insensitive header mapping, so lookups are not limited to the capitalization used when you set the name.
Can I use a Session for calls to different hosts?
You can, but keep host-specific credentials and other sensitive defaults scoped narrowly. In particular, avoid setting a short-lived token as a default on a Session shared across unrelated hosts.
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.




