25% off everything for the next 48 hours — use code HEART at checkoutGet 25% off
← All articles

Tutorials

How to Read HTTP Response Headers

Daniel K. · August 18, 2026 · 5 min read


Response headers are the most under-read diagnostic in web scraping. When a request fails, the body usually tells you nothing useful and the headers tell you almost everything: whether you were rate-limited, how long to wait, whether you were served a cached response, and whether the far end can tell you are using a proxy.

Headers worth reading every time

HeaderWhat it tells you
Retry-AfterExactly how long to wait after a 429 or 503
Cache-Control, AgeWhether you got a cached copy and how old it is
LocationRedirect destination, and whether it changes host
Set-CookieSession state you probably need to keep
Content-EncodingCompression in use, which affects your byte accounting
Server, CF-RayWhat is in front of the origin

Rate limit headers

Many APIs publish their limits as you consume them, commonly as X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Reading them lets you pace against the actual budget instead of guessing and getting blocked. When you do get a 429, Retry-After is an instruction, not a suggestion — see handling 429 responses.

Reading them in code

Credentials are built from a separate variable below rather than pasted inline — a literal user:pass@host string in a page body can be rewritten by email-obfuscation filters.

import requests

endpoint = "geo.spyderproxy.com:12321"
creds = "USERNAME:PASSWORD"
proxy = f"http://{creds}@{endpoint}"

r = requests.get("https://example.com",
                 proxies={"http": proxy, "https": proxy}, timeout=30)

for name in ("Retry-After", "Cache-Control", "Age", "Server",
             "X-RateLimit-Remaining", "Content-Encoding"):
    if name in r.headers:
        print(f"{name}: {r.headers[name]}")

for hop in r.history:
    print("redirect:", hop.status_code, hop.headers.get("Location"))

Headers that expose a proxy

These are request headers, added by the proxy and seen by the destination: X-Forwarded-For, Via, X-Real-IP and Forwarded. If any of them carries your real address, the proxy is transparent and is disclosing exactly what you were trying to keep private. Our HTTP header checker shows precisely what arrives at the far end, which is the fastest way to catch this.

Security headers you will encounter

Strict-Transport-Security forces HTTPS for future requests. Content-Security-Policy restricts what a page may load, which matters when you are rendering in a headless browser and resources are silently blocked. Set-Cookie flags such as SameSite and Secure change whether your session survives a redirect.

A debugging habit

When something breaks, log the full response headers before anything else. A surprising share of "the site blocked me" reports turn out to be a redirect to a login page, a cached 403 with an Age of several hours, or a 429 with a Retry-After nobody read.

Frequently Asked Questions

Which response header tells me I am rate limited?

A 429 status with Retry-After, which gives the wait in seconds or as a date. Many APIs also publish X-RateLimit-Remaining and X-RateLimit-Reset as you consume the budget.

How can I tell if a proxy is leaking my IP?

Check the request headers arriving at the destination for X-Forwarded-For, Via or X-Real-IP containing your real address. Our HTTP header checker shows exactly what the far end receives.

What does the Age header mean?

How long, in seconds, a cached response has been held by an intermediary. A high Age on an error response often means you are being served a stale failure rather than being blocked now.

Why does my scraper see different headers than my browser?

Servers vary responses by User-Agent, Accept-Encoding and Accept-Language. If your client sends a different set than a browser, you often get a different response entirely.

Related: HTTP header checker · proxy pricing · all eight products.

Put this into practice.

See HTTP header checker ↗Start now ↗