psf/requests · error · TypeError

create_cookie() got unexpected keyword arguments

Error message

create_cookie() got unexpected keyword arguments: {list(badargs)}

What it means

Raised by requests.cookies.create_cookie when kwargs contain keys not in the supported cookie attribute set (name, value, version, port, domain, secure, expires, etc.). The function builds a strict result dict and rejects any unknown key, listing the offending names in the message. This protects against silently mistyped attributes that would otherwise be ignored or passed to cookielib.Cookie incorrectly.

Solutions

  1. Check the error message for the listed badargs and rename them to the supported keys (expires, secure, domain, path, comment, comment_url, rest, discard, rfc2109, version, port).
  2. If you need HttpOnly/SameSite semantics, pass them via rest={'HttpOnly': True} (rest is the supported extension dict).
  3. Pre-validate kwargs against the known key set before calling create_cookie.

Example fix

// before
create_cookie(name='sid', value='x', expiry=3600, httponly=True)

// after
create_cookie(
    name='sid', value='x', expires=int(time.time())+3600,
    rest={'HttpOnly': True},
)
Defensive patterns

Strategy: validation

Validate before calling

from requests.cookies import create_cookie

_ALLOWED = {'name','value','version','port','port_specified','domain','domain_specified',
            'domain_initial_dot','path','path_specified','secure','expires','discard',
            'comment','comment_url','rest','rfc2109'}

def safe_create_cookie(**kwargs):
    bad = set(kwargs) - _ALLOWED
    if bad:
        raise TypeError(f'unsupported cookie keys: {sorted(bad)}')
    return create_cookie(**kwargs)

Type guard

from typing import Any

_ALLOWED_COOKIE_KEYS = {'name','value','version','port','port_specified','domain',
    'domain_specified','domain_initial_dot','path','path_specified','secure','expires',
    'discard','comment','comment_url','rest','rfc2109'}

def is_valid_cookie_kwargs(d: dict[str, Any]) -> bool:
    return set(d).issubset(_ALLOWED_COOKIE_KEYS) and 'name' in d and 'value' in d

Try / catch

try:
    c = create_cookie(**attrs)
except TypeError as e:
    # filter to known keys and retry, or report
    attrs = {k: v for k, v in attrs.items() if k in _ALLOWED_COOKIE_KEYS}
    c = create_cookie(**attrs)

Prevention

When it happens

Trigger: Calling create_cookie() with a typo (e.g. expiry= instead of expires=, httponly= instead of rest={'HttpOnly': True}); passing an arbitrary dict of cookie attributes from user input without filtering; version changes that renamed a supported key.

Common situations: Building cookies from a config file or API payload that includes keys like 'samesite' or 'priority' which create_cookie does not model; copy-pasting cookie dicts from another library (e.g. httpx) whose schema differs.

Related errors


AI-assisted analysis of psf/requests@8068356288 (2026-08-11). Data as JSON: /api/errors/54e285bf1b53ddd3. Report an issue: GitHub.

Appendix: source

Thrown at src/requests/cookies.py:518

    result: dict[str, Any] = {
        "version": 0,
        "name": name,
        "value": value,
        "port": None,
        "domain": "",
        "path": "/",
        "secure": False,
        "expires": None,
        "discard": True,
        "comment": None,
        "comment_url": None,
        "rest": {"HttpOnly": None},
        "rfc2109": False,
    }

    badargs = set(kwargs) - set(result)
    if badargs:
        raise TypeError(
            f"create_cookie() got unexpected keyword arguments: {list(badargs)}"
        )

    result.update(kwargs)
    result["port_specified"] = bool(result["port"])
    result["domain_specified"] = bool(result["domain"])
    result["domain_initial_dot"] = result["domain"].startswith(".")
    result["path_specified"] = bool(result["path"])

    return cookielib.Cookie(**result)


def morsel_to_cookie(morsel: Morsel[Any]) -> Cookie:
    """Convert a Morsel object into a Cookie containing the one k/v pair."""

    expires: int | None = None
    if morsel["max-age"]:
        try:

View on GitHub (pinned to 8068356288)