You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Create a request to a service that returns mime type text/html with json body and escaped html inside a string
Observe the HTML getting highlighted and characters converted to their unescaped versions
Compare with piping to cat to remove preprocessing, where the characters are left as they are
Current result
For example, proxy dns.google but set it's return content-type to text/html (proxy_pass https://dns.google; add_header Content-Type text/html always; in nginx).
I’d like to clarify what’s going on under the hood:
By-design behavior for text/html
HTTPie treats any response labeled Content-Type: text/html as “opaque” text, so when you request pretty-printed JSON with --json it still (a) syntax-highlights it as HTML, and (b) hands the raw Python object to json.dumps(..., ensure_ascii=False). That parameter is explicitly chosen to improve human readability by unescaping \uXXXX sequences into their corresponding characters.
Why it feels like a bug
It only surfaces when a server mislabels a JSON payload as text/html. Because the JSON body contains escaped HTML ("\u003c"), you end up seeing < in the output, even though the original JSON literally contained \u003c.
Options to preserve your escapes
Fix upstream: Have your server use the correct Content-Type: application/json; charset=utf-8. Then HTTPie will (correctly) call json.dumps(..., ensure_ascii=True), preserving all \uXXXX sequences.
Workaround in HTTPie: You could add a flag (or patch) around that one call site in json.py to force ensure_ascii=True when you detect --json, or introduce a new option like --preserve-escapes.
Conclusion
The premature unescaping is indeed happening in HTTPie, but it’s an intentional readability feature for non-JSON content. The “real” bug is on the server side sending the wrong Content-Type header. If you’re blocked by a server you can’t change, we could consider adding a new HTTPie option to preserve all escapes regardless of content type. Let me know if you’d like to collaborate on implementing that!
Uh oh!
There was an error while loading. Please reload this page.
Checklist
Minimal reproduction code and steps
text/html
with json body and escaped html inside a stringCurrent result
For example, proxy
dns.google
but set it's return content-type to text/html (proxy_pass https://dns.google; add_header Content-Type text/html always;
in nginx).is the raw code, but without
|cat
gets rendered aswhich is incorrect and can be confusing
Expected result
Same as
|cat
output as there's no real HTML to prettifyAdditional information, screenshots, or code examples
The text was updated successfully, but these errors were encountered: