Jump to solution
Verify

The Fix

Upgrade to version 0.18.0 or later.

Based on closed encode/httpx issue #1404 · PR/commit linked

Jump to Verify Open PR/Commit
@@ -37,6 +37,26 @@ HTTPX uses `utf-8` for encoding `str` request bodies. For example, when using `c For response bodies, assuming the server didn't send an explicit encoding then HTTPX will do its best to figure out an appropriate encoding. Unlike Requests which uses the `chardet` library, HTTPX relies on a plainer fallback strategy (basically attempting UTF-8, or using Windows-1252 as a fallback). This strategy should be robust enough to handle the vast majority of use cases. +## Cookies + +If using a client instance, then cookies should always be set on the client rather than on a per-request basis.
repro.py
import flask app = flask.Flask(__name__) @app.route('/r') def r(): return "yes" if "test" in flask.request.cookies else "no" @app.route('/same_domain_redirect') def same_domain_redirect(): return flask.redirect("/r", code=302) @app.route('/cross_domain_redirect') def cross_domain_redirect(): return flask.redirect("http://localhost:5000/r", code=302) @app.route('/same_domain_redirect_expire') def same_domain_redirect_expire(): resp = flask.redirect("/r", code=302) resp.set_cookie('test', '', expires=0) return resp if __name__ == '__main__': app.run()
verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
fix.md
Option A — Upgrade to fixed release\nUpgrade to version 0.18.0 or later.\nWhen NOT to use: This fix is not suitable if per-request cookie handling is required for specific use cases.\n\n

Why This Fix Works in Production

  • Trigger: DIRECT_URL="" # your webhook.site URL
  • Mechanism: Cookies were not being persisted across redirects due to per-request cookie handling
  • Why the fix works: Deprecates the use of per-request cookies in favor of setting cookies on the client instance to ensure clearer expectations around cookie persistence, especially during redirects. (first fixed release: 0.18.0).
Production impact:
  • If left unfixed, this can cause silent data inconsistencies that propagate (bad cache entries, incorrect downstream decisions).

Why This Breaks in Prod

  • Cookies were not being persisted across redirects due to per-request cookie handling
  • Production symptom (often without a traceback): DIRECT_URL="" # your webhook.site URL

Proof / Evidence

  • GitHub issue: #1404
  • Fix PR: https://github.com/encode/httpx/pull/1574
  • First fixed release: 0.18.0
  • Reproduced locally: No (not executed)
  • Last verified: 2026-02-09
  • Confidence: 0.85
  • Did this fix it?: Yes (upstream fix exists)
  • Own content ratio: 0.52

Discussion

High-signal excerpts from the issue thread (symptoms, repros, edge-cases).

“I'm going to *tentatively* milestone this for 0.17, which I assume will be released next week. I don't think we *necessarily* need to act on…”
@lovelydinosaur · 2021-01-08 · confirmation · source
“@tomchristie Wouldn't the path of least resistance be to do what requests do, since the API looks so similar that any behavioral divergence from this…”
@JanPokorny · 2021-01-06 · source
“@JanPokorny No I think that's just an internal implementation note, the behavior stays the same: httpx.get(...) doesn't maintain cookies across calls. The throwaway client used…”
@florimondmanca · 2021-01-08 · source
“In my tests, this can be worked around by passing the cookies to the client object itself (instead of the individual get calls).”
@craigholm · 2020-12-05 · source

Failure Signature (Search String)

  • DIRECT_URL="" # your webhook.site URL
  • It's a bit awkward to explain why, but if we break it down to the two sub-calls...
Copy-friendly signature
signature.txt
Failure Signature ----------------- DIRECT_URL="" # your webhook.site URL It's a bit awkward to explain why, but if we break it down to the two sub-calls...

Error Message

Signature-only (no traceback captured)
error.txt
Error Message ------------- DIRECT_URL="" # your webhook.site URL It's a bit awkward to explain why, but if we break it down to the two sub-calls...

Minimal Reproduction

repro.py
import flask app = flask.Flask(__name__) @app.route('/r') def r(): return "yes" if "test" in flask.request.cookies else "no" @app.route('/same_domain_redirect') def same_domain_redirect(): return flask.redirect("/r", code=302) @app.route('/cross_domain_redirect') def cross_domain_redirect(): return flask.redirect("http://localhost:5000/r", code=302) @app.route('/same_domain_redirect_expire') def same_domain_redirect_expire(): resp = flask.redirect("/r", code=302) resp.set_cookie('test', '', expires=0) return resp if __name__ == '__main__': app.run()

What Broke

Requests after redirects did not include expected cookies, leading to inconsistent behavior.

Why It Broke

Cookies were not being persisted across redirects due to per-request cookie handling

Fix Options (Details)

Option A — Upgrade to fixed release Safe default (recommended)

Upgrade to version 0.18.0 or later.

When NOT to use: This fix is not suitable if per-request cookie handling is required for specific use cases.

Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.

Fix reference: https://github.com/encode/httpx/pull/1574

First fixed release: 0.18.0

Last verified: 2026-02-09. Validate in your environment.

Get updates

We publish verified fixes weekly. No spam.

Subscribe

When NOT to Use This Fix

  • This fix is not suitable if per-request cookie handling is required for specific use cases.

Verify Fix

verify
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

  • Add a CI check that diffs key outputs after upgrades (OpenAPI schema snapshots, JSON payload shapes, CLI output).
  • Upgrade behind a canary and run integration tests against the canary before 100% rollout.
  • Add a TLS smoke test that performs a real handshake in CI (include CA bundle validation and hostname checks).
  • Alert on handshake failures by error string and endpoint to catch cert/CA changes quickly.

Version Compatibility Table

VersionStatus
0.18.0 Fixed

Related Issues

No related fixes found.

Sources

We don’t republish the full GitHub discussion text. Use the links above for context.