The Fix
It looks like this has been fixed in urllib3 (shazow/urllib3#236) and I can't reproduce it in Requests 2.12.4, so we can probably close this out unless we want to add a test.
Based on closed psf/requests issue #1561
I wonder if urllib3 is lowercasing these.
It does. See [L244 of urllib3/response.py](https://github.com/shazow/urllib3/blob/master/urllib3/response.py#L244). I'm not totally convinced this is a bug. For the purposes of the comment, the phrase "the actual key" should more correctly read "the key that was added to the dictionary". The CID is functioning as intended.
@sigmavirus24, I don't feel like urllib3 is doing the wrong thing here. Do you agree?
It's been doing that for over a year so I would guess that this is perfectly fine otherwise we would have run into issues much sooner. In other words @Lukasa, I agree with you.
the reason why I report this bug is that I want to write a proxy based on web page, user directly input the URL in the site and web server fetch the page for user, this require the web server return the same headers back to user which get from remote server, of course, I can uppercase the header name by myself, just want to see if we can do this in requests library.
Well I can confirm one thing: This is not something requests will do for you. We specifically wrap the headers in a case insensitive dictionary. We have no need for the headers to come back cased as they are sent and most of our users don't need them that way either.
I consider this a bug. Traditionally, requests preserved the server's casing. I'm not sure what happened.
@kennethreitz Looks like urllib3 changed its behaviour. I'll see if we can fix it up upstream.
@Lukasa, if you look at the blame on that file though, the change was a year ago. Something quite possibly may have changed but it isn't on that line of that file. It is probably somewhere else and in a change far more recent.
I'm not convinced we haven't been doing this wrong for a while. The change is definitely in urllib3: take a look at the headers on the urllib3 response. =)
This bug will probably stay open a little while until we can sort something out in shazow/urllib3#236, so I renamed it to a clear statement of the symptoms. That way, hopefully, we won't get too many reopens of this issue. =D
It looks like this has been fixed in urllib3 (shazow/urllib3#236) and I can't reproduce it in Requests 2.12.4, so we can probably close this out unless we want to add a test.
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Apply the official fix\nIt looks like this has been fixed in urllib3 (shazow/urllib3#236) and I can't reproduce it in Requests 2.12.4, so we can probably close this out unless we want to add a test.\nWhen NOT to use: Do not use if it changes public behavior or if the failure cannot be reproduced.\n\n
Why This Fix Works in Production
- Trigger: Header keys lose their case
- Mechanism: It looks like this has been fixed in urllib3 (shazow/urllib3#236) and I can't reproduce it in Requests 2.12.4, so we can probably close this out unless we want to add a test.
Why This Breaks in Prod
- Production symptom (often without a traceback): @kennethreitz Looks like urllib3 changed its behaviour. I'll see if we can fix it up upstream.
Proof / Evidence
- GitHub issue: #1561
- Reproduced locally: No (not executed)
- Last verified: 2026-02-04
- Confidence: 0.00
- Did this fix it?: No (no upstream fix linked)
- Own content ratio: 0.39
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“It looks like this has been fixed in urllib3 (shazow/urllib3#236) and I can't reproduce it in Requests 2.12.4, so we can probably close this out…”
“Hmm, this is a puzzling one. I see the same behaviour as you, plus this oddity: I wonder if urllib3 is lowercasing these.”
“It does”
“It's been doing that for over a year so I would guess that this is perfectly fine otherwise we would have run into issues much…”
Failure Signature (Search String)
- Header keys lose their case
Copy-friendly signature
Failure Signature
-----------------
@kennethreitz Looks like urllib3 changed its behaviour. I'll see if we can fix it up upstream.
@Lukasa, if you look at the blame on that file though, the change was a year ago. Something quite possibly may have changed but it isn't on that line of that file. It is probably somewhere else and in a change far more recent.
Error Message
Signature-only (no traceback captured)
Error Message
-------------
@kennethreitz Looks like urllib3 changed its behaviour. I'll see if we can fix it up upstream.
@Lukasa, if you look at the blame on that file though, the change was a year ago. Something quite possibly may have changed but it isn't on that line of that file. It is probably somewhere else and in a change far more recent.
Minimal Reproduction
I wonder if urllib3 is lowercasing these.
It does. See [L244 of urllib3/response.py](https://github.com/shazow/urllib3/blob/master/urllib3/response.py#L244). I'm not totally convinced this is a bug. For the purposes of the comment, the phrase "the actual key" should more correctly read "the key that was added to the dictionary". The CID is functioning as intended.
@sigmavirus24, I don't feel like urllib3 is doing the wrong thing here. Do you agree?
It's been doing that for over a year so I would guess that this is perfectly fine otherwise we would have run into issues much sooner. In other words @Lukasa, I agree with you.
the reason why I report this bug is that I want to write a proxy based on web page, user directly input the URL in the site and web server fetch the page for user, this require the web server return the same headers back to user which get from remote server, of course, I can uppercase the header name by myself, just want to see if we can do this in requests library.
Well I can confirm one thing: This is not something requests will do for you. We specifically wrap the headers in a case insensitive dictionary. We have no need for the headers to come back cased as they are sent and most of our users don't need them that way either.
I consider this a bug. Traditionally, requests preserved the server's casing. I'm not sure what happened.
@kennethreitz Looks like urllib3 changed its behaviour. I'll see if we can fix it up upstream.
@Lukasa, if you look at the blame on that file though, the change was a year ago. Something quite possibly may have changed but it isn't on that line of that file. It is probably somewhere else and in a change far more recent.
I'm not convinced we haven't been doing this wrong for a while. The change is definitely in urllib3: take a look at the headers on the urllib3 response. =)
This bug will probably stay open a little while until we can sort something out in shazow/urllib3#236, so I renamed it to a clear statement of the symptoms. That way, hopefully, we won't get too many reopens of this issue. =D
It looks like this has been fixed in urllib3 (shazow/urllib3#236) and I can't reproduce it in Requests 2.12.4, so we can probably close this out unless we want to add a test.
Fix Options (Details)
Option A — Apply the official fix
It looks like this has been fixed in urllib3 (shazow/urllib3#236) and I can't reproduce it in Requests 2.12.4, so we can probably close this out unless we want to add a test.
Fix reference: https://github.com/psf/requests/issues/1561
When NOT to Use This Fix
- Do not use if it changes public behavior or if the failure cannot be reproduced.
Verify Fix
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Did This Fix Work in Your Case?
Quick signal helps us prioritize which fixes to verify and improve.
Prevention
- Capture the exact failing error string in logs and tests so you can reproduce via a minimal script.
- Pin production dependencies and upgrade only with a reproducible test that hits the failing path.
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.