psf/requests · error · InvalidHeader
Invalid leading whitespace, reserved character(s), or return
Error message
Invalid leading whitespace, reserved character(s), or return character(s) in header {header_kind}: {header_part!r} What it means
Raised as `requests.exceptions.InvalidHeader` from `_validate_header_part()` in `src/requests/utils.py:1116` when a header name or value fails the `_HEADER_VALIDATORS_STR`/`_HEADER_VALIDATORS_BYTE` regex. These validators reject leading whitespace and CR/LF (return) characters in values, and reserved/illegal characters in names. This is primarily a security control against HTTP header injection (request smuggling / response splitting via embedded '\r\n'), added after CVE-2022-32213-class issues across HTTP clients.
Source
Thrown at src/requests/utils.py:1116
def _validate_header_part(
header: tuple[str | bytes, str | bytes],
header_part: str | bytes,
header_validator_index: int,
) -> None:
if isinstance(header_part, str):
validator = _HEADER_VALIDATORS_STR[header_validator_index]
elif isinstance(header_part, bytes):
# runtime guard for non-str/bytes input
validator = _HEADER_VALIDATORS_BYTE[header_validator_index]
else:
raise InvalidHeader(
f"Header part ({header_part!r}) from {header} "
f"must be of type str or bytes, not {type(header_part)}"
)
if not validator.match(header_part): # type: ignore[arg-type]
header_kind = "name" if header_validator_index == 0 else "value"
raise InvalidHeader(
f"Invalid leading whitespace, reserved character(s), or return "
f"character(s) in header {header_kind}: {header_part!r}"
)
def urldefragauth(url: str) -> str:
"""
Given a url remove the fragment and the authentication part.
:rtype: str
"""
scheme, netloc, path, params, query, _fragment = urlparse(url)
# see func:`prepend_scheme_if_needed`
if not netloc:
netloc, path = path, netloc
netloc = netloc.rsplit("@", 1)[-1]View on GitHub ↗ (pinned to 414f0513c3)
Solutions
- Strip the value: `headers={'Authorization': token.strip()}` — newlines from `read()` or env vars are the most common cause.
- Never place raw user input into headers; sanitize or reject values containing '\r' or '\n'.
- Remove the colon or spaces from the header name — pass 'Authorization', not 'Authorization:'.
- If the value is legitimately multi-line, it cannot be a single HTTP header; restructure (e.g. base64-encode it).
Example fix
# before
token = open('token.txt').read() # ends with '\n'
requests.get(url, headers={'Authorization': f'Bearer {token}'})
# after
token = open('token.txt').read().strip()
requests.get(url, headers={'Authorization': f'Bearer {token}'}) Defensive patterns
Strategy: validation
Validate before calling
import re
_INVALID = re.compile(r'^\s|[\r\n]')
def header_value_is_safe(value):
s = value.decode('latin-1') if isinstance(value, bytes) else value
return not _INVALID.search(s)
assert all(header_value_is_safe(v) for v in headers.values()), 'header contains leading whitespace or CR/LF' Try / catch
try:
resp = requests.get(url, headers=headers)
except requests.exceptions.InvalidHeader as e:
# leading whitespace or CR/LF in a header — often an injection attempt
log.warning('Rejected unsafe header: %s', e) Prevention
- Strip whitespace from header values built from user input (value.strip())
- Reject or sanitize CR/LF in any user-controlled value destined for a header — this check is your defense against header injection, don't work around it
- Validate header names against RFC 7230 token characters at the trust boundary
When it happens
Trigger: Any request where a header value contains '\r' or '\n' (e.g. `headers={'X-Note': 'line1\nline2'}`), starts with a space or tab, or where a header name contains characters outside the RFC 7230 token set (spaces, colons, non-ASCII). The message's `header_kind` tells you whether the name or the value failed.
Common situations: Header values read from files or env vars that carry a trailing/embedded newline (e.g. `open('token.txt').read()` without `.strip()`); user input interpolated into headers (injection attempt or accident); multi-line strings from YAML config; copy-pasted tokens with leading whitespace; header names with a stray trailing colon like 'Authorization:'.
Related errors
- Header part ({header_part!r}) from {header} must be of type
- Files must be provided.
- Data must not be a string.
- Invalid URL {url!r}: No scheme supplied. Perhaps you meant h
- URL has an invalid label.
AI-assisted analysis of psf/requests@414f0513c3 (2026-07-31).
Data as JSON: /data/errors/b89494c0d9bf600f.json.
Report an issue: GitHub ↗.