{"id":51058520,"url":"https://github.com/cumulus13/pyheaderparse","last_synced_at":"2026-06-22T23:02:14.534Z","repository":{"id":325624507,"uuid":"1101794953","full_name":"cumulus13/pyheaderparse","owner":"cumulus13","description":"A robust HTTP header and cookie parser library","archived":false,"fork":false,"pushed_at":"2025-11-22T11:13:45.000Z","size":2127,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-11-22T13:06:37.955Z","etag":null,"topics":["dict","headers","modern","parser","production","python","raw","robust","smart"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/pyheaderparse","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cumulus13.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/contributing.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-22T08:50:56.000Z","updated_at":"2025-11-22T11:19:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cumulus13/pyheaderparse","commit_stats":null,"previous_names":["cumulus13/pyheaderparse"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/cumulus13/pyheaderparse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cumulus13%2Fpyheaderparse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cumulus13%2Fpyheaderparse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cumulus13%2Fpyheaderparse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cumulus13%2Fpyheaderparse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cumulus13","download_url":"https://codeload.github.com/cumulus13/pyheaderparse/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cumulus13%2Fpyheaderparse/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34668499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dict","headers","modern","parser","production","python","raw","robust","smart"],"created_at":"2026-06-22T23:02:12.567Z","updated_at":"2026-06-22T23:02:14.523Z","avatar_url":"https://github.com/cumulus13.png","language":"Python","funding_links":["https://www.buymeacoffee.com/cumulus13","https://ko-fi.com/cumulus13","https://www.patreon.com/cumulus13"],"categories":[],"sub_categories":[],"readme":"# pyheaderparse\n\nA robust HTTP header and cookie parser library for Python.\n\n[![PyPI version](https://badge.fury.io/py/pyheaderparse.svg)](https://badge.fury.io/py/pyheaderparse)\n[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Documentation](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://pyheaderparse.readthedocs.io/)\n\n## Features\n\n- **Complete Header Parsing**: Parse all standard HTTP headers including Content-Type, Accept, Cache-Control, and more\n- **Cookie Support**: Full cookie parsing with multiple extraction methods\n- **Kwargs Support**: Create and modify headers/cookies using keyword arguments\n- **Client Hints**: Parse modern `Sec-CH-UA-*` headers\n- **Type Safety**: Full type hints for IDE support\n- **Zero Dependencies**: No external dependencies required\n- **CLI Tool**: Command-line interface for quick parsing\n- **Method Chaining**: Fluent API for easy manipulation\n- **Production Ready**: Comprehensive test suite and error handling\n\n## Installation\n\n```bash\npip install pyheaderparse\n```\n\n## Documentation\n\n[![Documentation](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://pyheaderparse.readthedocs.io/)\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- [HeaderParser](#headerparser)\n  - [Parsing Headers](#parsing-headers)\n  - [Setting Headers](#setting-headers)\n  - [Accessing Headers](#accessing-headers)\n  - [Special Header Parsing](#special-header-parsing)\n- [CookieParser](#cookieparser)\n  - [Parsing Cookies](#parsing-cookies)\n  - [Setting Cookies](#setting-cookies)\n  - [Output Methods](#output-methods)\n- [CLI Usage](#cli-usage)\n- [API Reference](#api-reference)\n\n---\n\n## Quick Start\n\n```python\nfrom parser_header import HeaderParser, CookieParser\n\n# Parse raw headers\nraw = \"\"\"content-type: application/json\ncontent-length: 1024\ncookie: session=abc123; user=john\n\"\"\"\nparser = HeaderParser(raw)\nprint(parser.content_type)  # 'application/json'\nprint(parser.get_cookies_as_dict())  # {'session': 'abc123', 'user': 'john'}\n\n# Or create from kwargs\nparser = HeaderParser(content_type='application/json', user_agent='MyApp/1.0')\nprint(parser.to_raw())\n# Output:\n# content-type: application/json\n# user-agent: MyApp/1.0\n```\n\n---\n\n## HeaderParser\n\n### Parsing Headers\n\n#### From Raw String/Bytes\n\n```python\nfrom parser_header import HeaderParser\n\nraw_headers = \"\"\"content-length: 1171\ncontent-type: application/json\nuser-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/144.0.0.0\naccept: */*\naccept-language: en-US,en;q=0.9,es;q=0.8\naccept-encoding: gzip, deflate, br, zstd\ncache-control: max-age=3600, public\ndnt: 1\nsec-ch-ua: \"Chrome\";v=\"144\", \"Not A Brand\";v=\"8\"\nsec-ch-ua-mobile: ?0\nsec-ch-ua-platform: \"Windows\"\norigin: https://example.com\nreferer: https://example.com/page\ncookie: session=abc123\ncookie: uid=user456\npriority: u=1, i\n\"\"\"\n\nparser = HeaderParser(raw_headers)\n\nprint(f\"Total headers: {len(parser)}\")\n# Output: Total headers: 15\n\nprint(f\"Header names: {parser.keys()}\")\n# Output: Header names: ['content-length', 'content-type', 'user-agent', 'accept', ...]\n```\n\n#### From Kwargs (Underscore → Hyphen Auto-Conversion)\n\n```python\nfrom parser_header import HeaderParser\n\n# Underscores in key names are automatically converted to hyphens\nparser = HeaderParser(\n    content_type='application/json',\n    content_length='1024',\n    user_agent='MyApp/1.0',\n    x_request_id='req-12345',\n    x_custom_header='custom-value',\n    accept='*/*'\n)\n\nprint(parser.to_raw())\n# Output:\n# content-type: application/json\n# content-length: 1024\n# user-agent: MyApp/1.0\n# x-request-id: req-12345\n# x-custom-header: custom-value\n# accept: */*\n\nprint('x-request-id' in parser)  # True\nprint('x_request_id' in parser)  # True (also works)\n```\n\n#### Mixed: Raw Data + Kwargs\n\n```python\nfrom parser_header import HeaderParser\n\nraw = \"content-type: text/html\\naccept: */*\"\n\nparser = HeaderParser(raw, user_agent='Mozilla/5.0', x_token='abc123')\n\nprint(parser.to_dict())\n# Output:\n# {\n#     'content-type': HeaderValue(value='text/html', params={}),\n#     'accept': [{'type': '*/*', 'q': 1.0}],\n#     'user-agent': 'Mozilla/5.0',\n#     'x-token': 'abc123'\n# }\n```\n\n#### From Dict or Factory Methods\n\n```python\nfrom parser_header import HeaderParser\n\n# From dictionary\nheaders_dict = {\n    'Content-Type': 'application/json',\n    'Authorization': 'Bearer token123',\n    'X-Request-ID': 'req-456'\n}\nparser = HeaderParser.from_dict(headers_dict)\n\nprint(parser.content_type)  # 'application/json'\nprint(parser.get('authorization'))  # 'Bearer token123'\n\n# From kwargs factory\nparser = HeaderParser.from_kwargs(\n    content_type='text/xml',\n    cache_control='no-cache'\n)\nprint(parser.to_raw())\n# Output:\n# content-type: text/xml\n# cache-control: no-cache\n```\n\n#### From Requests Response\n\n```python\nfrom parser_header import HeaderParser\nimport requests\n\nresponse = requests.get('https://httpbin.org/get')\nparser = HeaderParser.from_requests_response(response)\n\nprint(parser.content_type)  # 'application/json'\nprint(parser.get('date'))   # 'Sat, 22 Nov 2025 10:30:00 GMT'\n```\n\n---\n\n### Setting Headers\n\n#### Using set() Method\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\n\n# Positional arguments\nparser.set('Content-Type', 'application/json')\n\n# Kwargs only\nparser.set(user_agent='Mozilla/5.0', accept='*/*')\n\n# Mixed positional + kwargs\nparser.set('Authorization', 'Bearer token', x_request_id='12345')\n\nprint(parser.to_raw())\n# Output:\n# content-type: application/json\n# user-agent: Mozilla/5.0\n# accept: */*\n# authorization: Bearer token\n# x-request-id: 12345\n```\n\n#### Using set_raw() (No Value Parsing)\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\n\n# set() parses the value\nparser.set('cache-control', 'max-age=3600, public')\nprint(parser.get('cache-control'))\n# Output: {'max-age': 3600, 'public': True}\n\n# set_raw() keeps value as-is\nparser.set_raw('x-raw-header', 'max-age=3600, public')\nprint(parser.get('x-raw-header'))\n# Output: 'max-age=3600, public'\n```\n\n#### Using Bracket Notation\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\n\nparser['Content-Type'] = 'application/json'\nparser['X-Custom'] = 'value'\n\nprint(parser['content-type'])  # application/json (case-insensitive)\n\ndel parser['X-Custom']\nprint('x-custom' in parser)  # False\n```\n\n#### Using update() Method\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser(content_type='text/html')\n\n# Update from dict\nparser.update({'Accept': '*/*', 'Accept-Language': 'en-US'})\n\n# Update from kwargs\nparser.update(user_agent='TestAgent', x_token='abc')\n\n# Mixed\nparser.update({'Cache-Control': 'no-cache'}, dnt='1')\n\nprint(parser.to_raw())\n# Output:\n# content-type: text/html\n# accept: */*\n# accept-language: en-US\n# user-agent: TestAgent\n# x-token: abc\n# cache-control: no-cache\n# dnt: 1\n```\n\n#### Method Chaining\n\n```python\nfrom parser_header import HeaderParser\n\nparser = (\n    HeaderParser()\n    .set(content_type='application/json')\n    .set(accept='*/*')\n    .set(user_agent='MyApp/1.0')\n    .set_cookie(session='abc123', user='john')\n)\n\nprint(parser.to_raw())\n# Output:\n# content-type: application/json\n# accept: */*\n# user-agent: MyApp/1.0\n\nprint(parser.get_cookies_as_header())\n# Output: session=abc123; user=john\n```\n\n#### Removing and Clearing\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser(\n    content_type='application/json',\n    accept='*/*',\n    user_agent='Test',\n    x_custom='value'\n)\n\n# Remove specific headers\nparser.remove('x-custom', 'accept')\nprint(parser.keys())\n# Output: ['content-type', 'user-agent']\n\n# Clear all\nparser.clear()\nprint(len(parser))  # 0\n```\n\n---\n\n### Accessing Headers\n\n#### Basic Access\n\n```python\nfrom parser_header import HeaderParser\n\nraw = \"\"\"content-type: application/json; charset=utf-8\ncontent-length: 1024\nuser-agent: Mozilla/5.0\n\"\"\"\n\nparser = HeaderParser(raw)\n\n# get() method (case-insensitive, with default)\nprint(parser.get('Content-Type'))      # HeaderValue(value='application/json', params={'charset': 'utf-8'})\nprint(parser.get('X-Missing', 'N/A'))  # 'N/A'\n\n# Bracket notation\nprint(parser['user-agent'])  # 'Mozilla/5.0'\n\n# Property shortcuts\nprint(parser.content_type)    # 'application/json'\nprint(parser.content_length)  # 1024 (as int)\nprint(parser.user_agent)      # 'Mozilla/5.0'\nprint(parser.origin)          # None\nprint(parser.referer)         # None\n\n# Check existence\nprint('content-type' in parser)  # True\nprint('x-missing' in parser)     # False\n```\n\n#### Iteration\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser(content_type='application/json', accept='*/*', dnt='1')\n\n# Iterate keys\nfor name in parser:\n    print(f\"{name}: {parser[name]}\")\n# Output:\n# content-type: application/json\n# accept: [{'type': '*/*', 'q': 1.0}]\n# dnt: True\n\n# Get all keys, values, items\nprint(parser.keys())    # ['content-type', 'accept', 'dnt']\nprint(parser.values())  # [HeaderValue(...), [{'type': '*/*', 'q': 1.0}], True]\nprint(parser.items())   # [('content-type', HeaderValue(...)), ...]\n```\n\n#### Export/Conversion\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser(\n    content_type='application/json',\n    accept='*/*',\n    dnt='1'\n)\n\n# To dictionary\nprint(parser.to_dict())\n# Output:\n# {\n#     'content-type': HeaderValue(value='application/json', params={}),\n#     'accept': [{'type': '*/*', 'q': 1.0}],\n#     'dnt': True\n# }\n\n# To dictionary with stringified values\nprint(parser.to_dict(stringify=True))\n# Output:\n# {\n#     'content-type': 'application/json',\n#     'accept': \"[{'type': '*/*', 'q': 1.0}]\",\n#     'dnt': 'True'\n# }\n\n# To raw format\nprint(parser.to_raw())\n# Output:\n# content-type: application/json\n# accept: [{'type': '*/*', 'q': 1.0}]\n# dnt: 1\n\n# To requests-compatible dict (all string values)\nheaders = parser.to_requests_headers()\nprint(headers)\n# Output: {'content-type': 'application/json', 'accept': \"*/*\", 'dnt': '1'}\n\n# Use with requests library\nimport requests\nresponse = requests.get('https://example.com', headers=headers)\n```\n\n---\n\n### Special Header Parsing\n\n#### Content-Type with Parameters\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\nparser.set('content-type', 'text/html; charset=utf-8; boundary=something')\n\nct = parser.get('content-type')\nprint(f\"Type: {ct}\")           # HeaderValue(value='text/html', params={'charset': 'utf-8', 'boundary': 'something'})\nprint(f\"Value: {ct.value}\")    # 'text/html'\nprint(f\"Charset: {ct.params['charset']}\")    # 'utf-8'\nprint(f\"Boundary: {ct.params['boundary']}\")  # 'something'\n\n# Property returns just the value\nprint(parser.content_type)  # 'text/html'\n```\n\n#### Accept-Language with Quality Values\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\nparser.set('accept-language', 'en-US,en;q=0.9,es;q=0.8,fr;q=0.7')\n\nlangs = parser.get('accept-language')\nprint(langs)\n# Output (sorted by quality, descending):\n# [\n#     {'lang': 'en-US', 'q': 1.0},\n#     {'lang': 'en', 'q': 0.9},\n#     {'lang': 'es', 'q': 0.8},\n#     {'lang': 'fr', 'q': 0.7}\n# ]\n\n# Get preferred language\nprint(f\"Preferred: {langs[0]['lang']}\")  # 'en-US'\n```\n\n#### Accept Header\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\nparser.set('accept', 'text/html,application/json;q=0.9,*/*;q=0.8')\n\naccept = parser.get('accept')\nprint(accept)\n# Output:\n# [\n#     {'type': 'text/html', 'q': 1.0},\n#     {'type': 'application/json', 'q': 0.9},\n#     {'type': '*/*', 'q': 0.8}\n# ]\n```\n\n#### Cache-Control\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\nparser.set('cache-control', 'max-age=3600, public, no-transform')\n\ncache = parser.get('cache-control')\nprint(cache)\n# Output:\n# {\n#     'max-age': 3600,        # Parsed as int\n#     'public': True,\n#     'no-transform': True\n# }\n\nprint(f\"Max age: {cache['max-age']} seconds\")  # 3600\n```\n\n#### Boolean Headers (DNT, Sec-GPC)\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\nparser.set('dnt', '1')\nparser.set('sec-gpc', '1')\nparser.set('upgrade-insecure-requests', '1')\n\nprint(parser.get('dnt'))      # True (parsed as boolean)\nprint(parser.get('sec-gpc'))  # True\nprint(parser.get('upgrade-insecure-requests'))  # True\n```\n\n#### Client Hints (Sec-CH-UA-*)\n\n```python\nfrom parser_header import HeaderParser\n\nraw = \"\"\"sec-ch-ua: \"Chrome\";v=\"144\", \"Not A Brand\";v=\"8\", \"Chromium\";v=\"144\"\nsec-ch-ua-mobile: ?0\nsec-ch-ua-platform: \"Windows\"\nsec-ch-ua-arch: \"x86\"\nsec-ch-ua-bitness: \"64\"\nsec-ch-ua-full-version: \"144.0.7524.3\"\nsec-ch-ua-platform-version: \"15.0.0\"\n\"\"\"\n\nparser = HeaderParser(raw)\n\n# sec-ch-ua parsed as list of brands\nua = parser.get('sec-ch-ua')\nprint(ua)\n# Output:\n# [\n#     {'brand': 'Chrome', 'version': '144'},\n#     {'brand': 'Not A Brand', 'version': '8'},\n#     {'brand': 'Chromium', 'version': '144'}\n# ]\n\n# sec-ch-ua-mobile parsed as boolean\nprint(parser.get('sec-ch-ua-mobile'))  # False\n\n# Other values have quotes stripped\nprint(parser.get('sec-ch-ua-platform'))  # 'Windows'\nprint(parser.get('sec-ch-ua-arch'))      # 'x86'\n\n# Get all client hints\nhints = parser.get_client_hints()\nprint(hints)\n# Output:\n# {\n#     'sec-ch-ua': [{'brand': 'Chrome', 'version': '144'}, ...],\n#     'sec-ch-ua-mobile': False,\n#     'sec-ch-ua-platform': 'Windows',\n#     'sec-ch-ua-arch': 'x86',\n#     'sec-ch-ua-bitness': '64',\n#     'sec-ch-ua-full-version': '144.0.7524.3',\n#     'sec-ch-ua-platform-version': '15.0.0'\n# }\n```\n\n#### Priority Header\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser()\nparser.set('priority', 'u=1, i')\n\npriority = parser.get('priority')\nprint(priority)\n# Output: {'u': '1', 'i': True}\n```\n\n#### Sec-Fetch Metadata\n\n```python\nfrom parser_header import HeaderParser\n\nraw = \"\"\"sec-fetch-site: same-origin\nsec-fetch-mode: cors\nsec-fetch-dest: empty\n\"\"\"\n\nparser = HeaderParser(raw)\n\nmetadata = parser.get_sec_fetch_metadata()\nprint(metadata)\n# Output:\n# {\n#     'site': 'same-origin',\n#     'mode': 'cors',\n#     'dest': 'empty',\n#     'user': ''\n# }\n```\n\n#### CORS and AJAX Detection\n\n```python\nfrom parser_header import HeaderParser\n\nparser = HeaderParser(\n    origin='https://example.com',\n    x_requested_with='XMLHttpRequest'\n)\n\nprint(parser.is_cors())  # True\nprint(parser.is_ajax())  # True\n\nparser2 = HeaderParser(user_agent='Mozilla/5.0')\nprint(parser2.is_cors())  # False\nprint(parser2.is_ajax())  # False\n```\n\n---\n\n## CookieParser\n\n### Parsing Cookies\n\n#### From Raw String (Multiple Lines)\n\n```python\nfrom parser_header import CookieParser\n\nraw_cookies = \"\"\"cookie: nonce=Ofymgy29\ncookie: sz=1490\ncookie: pr=1.25\ncookie: uid=2ca13899eb7a\ncookie: sid=1:KUo/b68Cp0mhPre4OYgcLF\ncookie: xsrf=a9a6c92dc170\n\"\"\"\n\ncookies = CookieParser(raw_cookies)\n\nprint(f\"Total cookies: {len(cookies)}\")\n# Output: Total cookies: 6\n\nprint(cookies.to_dict())\n# Output:\n# {\n#     'nonce': 'Ofymgy29',\n#     'sz': '1490',\n#     'pr': '1.25',\n#     'uid': '2ca13899eb7a',\n#     'sid': '1:KUo/b68Cp0mhPre4OYgcLF',\n#     'xsrf': 'a9a6c92dc170'\n# }\n```\n\n#### From Single Line (Semicolon-Separated)\n\n```python\nfrom parser_header import CookieParser\n\nsingle_line = \"cookie: session=abc123; user=john; token=xyz789\"\n\ncookies = CookieParser(single_line)\n\nprint(cookies.to_dict())\n# Output: {'session': 'abc123', 'user': 'john', 'token': 'xyz789'}\n```\n\n#### From Kwargs\n\n```python\nfrom parser_header import CookieParser\n\n# Underscores converted to hyphens\ncookies = CookieParser(\n    session='abc123',\n    user_id='12345',\n    auth_token='xyz789',\n    refresh_token='refresh123'\n)\n\nprint(cookies.to_dict())\n# Output:\n# {\n#     'session': 'abc123',\n#     'user-id': '12345',\n#     'auth-token': 'xyz789',\n#     'refresh-token': 'refresh123'\n# }\n\nprint(cookies.to_cookie_header())\n# Output: session=abc123; user-id=12345; auth-token=xyz789; refresh-token=refresh123\n```\n\n#### Mixed: Raw + Kwargs\n\n```python\nfrom parser_header import CookieParser\n\nraw = \"cookie: existing=value\"\n\ncookies = CookieParser(raw, new_cookie='new_value', another='test')\n\nprint(cookies.to_dict())\n# Output:\n# {\n#     'existing': 'value',\n#     'new-cookie': 'new_value',\n#     'another': 'test'\n# }\n```\n\n#### From Dict or Factory Methods\n\n```python\nfrom parser_header import CookieParser\n\n# From dictionary\ncookies = CookieParser.from_dict({\n    'session': 'abc',\n    'user': 'john',\n    'token': 'xyz'\n})\nprint(cookies.to_cookie_header())\n# Output: session=abc; user=john; token=xyz\n\n# From kwargs factory\ncookies = CookieParser.from_kwargs(\n    session='test123',\n    remember_me='true'\n)\nprint(cookies.to_cookie_header())\n# Output: session=test123; remember-me=true\n```\n\n---\n\n### Setting Cookies\n\n#### Using set() Method\n\n```python\nfrom parser_header import CookieParser\n\ncookies = CookieParser()\n\n# Positional arguments\ncookies.set('session', 'abc123')\n\n# Kwargs only\ncookies.set(user='john', token='xyz')\n\n# Mixed\ncookies.set('admin', 'true', refresh_token='refresh123')\n\nprint(cookies.to_dict())\n# Output:\n# {\n#     'session': 'abc123',\n#     'user': 'john',\n#     'token': 'xyz',\n#     'admin': 'true',\n#     'refresh-token': 'refresh123'\n# }\n```\n\n#### Using Bracket Notation\n\n```python\nfrom parser_header import CookieParser\n\ncookies = CookieParser()\n\ncookies['session'] = 'abc123'\ncookies['user'] = 'john'\n\nprint(cookies['session'])  # 'abc123'\n\ndel cookies['user']\nprint('user' in cookies)  # False\n```\n\n#### Using update() Method\n\n```python\nfrom parser_header import CookieParser\n\ncookies = CookieParser(existing='value')\n\n# From dict\ncookies.update({'new1': 'val1', 'new2': 'val2'})\n\n# From kwargs\ncookies.update(new3='val3', new4='val4')\n\n# Mixed\ncookies.update({'from_dict': 'yes'}, from_kwargs='also_yes')\n\nprint(cookies.to_dict())\n# Output:\n# {\n#     'existing': 'value',\n#     'new1': 'val1',\n#     'new2': 'val2',\n#     'new3': 'val3',\n#     'new4': 'val4',\n#     'from-dict': 'yes',\n#     'from-kwargs': 'also_yes'\n# }\n```\n\n#### Method Chaining\n\n```python\nfrom parser_header import CookieParser\n\ncookies = (\n    CookieParser()\n    .set('session', 'abc')\n    .set(user='john')\n    .set(token='xyz', admin='false')\n    .remove('admin')\n)\n\nprint(cookies.to_cookie_header())\n# Output: session=abc; user=john; token=xyz\n```\n\n#### Removing and Clearing\n\n```python\nfrom parser_header import CookieParser\n\ncookies = CookieParser(a='1', b='2', c='3', d='4')\n\n# Remove specific cookies\ncookies.remove('a', 'b')\nprint(cookies.keys())  # ['c', 'd']\n\n# Clear all\ncookies.clear()\nprint(len(cookies))  # 0\n```\n\n---\n\n### Output Methods\n\n#### to_cookie_header() - Cookie Header Format\n\n```python\nfrom parser_header import CookieParser\n\ncookies = CookieParser(session='abc', user='john', token='xyz')\n\n# Basic usage\nheader = cookies.to_cookie_header()\nprint(header)\n# Output: session=abc; user=john; token=xyz\n\n# With additional cookies via kwargs\nheader = cookies.to_cookie_header(extra='value', another='test')\nprint(header)\n# Output: session=abc; user=john; token=xyz; extra=value; another=test\n\n# Use in HTTP request\nimport urllib.request\nreq = urllib.request.Request('https://example.com')\nreq.add_header('Cookie', cookies.to_cookie_header())\n```\n\n#### to_dict() - Dictionary Format\n\n```python\nfrom parser_header import CookieParser\n\ncookies = CookieParser(session='abc', user='john')\n\n# Basic usage\nd = cookies.to_dict()\nprint(d)\n# Output: {'session': 'abc', 'user': 'john'}\n\n# With additional cookies\nd = cookies.to_dict(extra='value')\nprint(d)\n# Output: {'session': 'abc', 'user': 'john', 'extra': 'value'}\n\n# Use with requests library\nimport requests\nresponse = requests.get('https://example.com', cookies=cookies.to_dict())\n```\n\n#### Accessing Individual Cookies\n\n```python\nfrom parser_header import CookieParser\n\ncookies = CookieParser(session='abc', user_id='123', auth_token='xyz')\n\n# get() with default\nprint(cookies.get('session'))           # 'abc'\nprint(cookies.get('missing', 'N/A'))    # 'N/A'\n\n# Underscore/hyphen interchangeable\nprint(cookies.get('user-id'))     # '123'\nprint(cookies.get('user_id'))     # '123'\nprint(cookies.get('auth-token'))  # 'xyz'\nprint(cookies.get('auth_token'))  # 'xyz'\n\n# Bracket notation\nprint(cookies['session'])  # 'abc'\n\n# Iteration\nfor name in cookies:\n    print(f\"{name}={cookies[name]}\")\n# Output:\n# session=abc\n# user-id=123\n# auth-token=xyz\n\n# Keys, values, items\nprint(cookies.keys())    # ['session', 'user-id', 'auth-token']\nprint(cookies.values())  # ['abc', '123', 'xyz']\nprint(cookies.items())   # [('session', 'abc'), ('user-id', '123'), ('auth-token', 'xyz')]\n```\n\n---\n\n### Cookies via HeaderParser\n\n```python\nfrom parser_header import HeaderParser\n\nraw = \"\"\"content-type: application/json\ncookie: session=abc123\ncookie: user=john\ncookie: token=xyz789\n\"\"\"\n\nparser = HeaderParser(raw)\n\n# Access CookieParser instance\nprint(parser.cookies.to_dict())\n# Output: {'session': 'abc123', 'user': 'john', 'token': 'xyz789'}\n\n# Shortcut methods\nprint(parser.get_cookie('session'))      # 'abc123'\nprint(parser.get_cookie('missing', ''))  # ''\nprint(parser.get_cookies_as_header())    # 'session=abc123; user=john; token=xyz789'\nprint(parser.get_cookies_as_dict())      # {'session': 'abc123', 'user': 'john', 'token': 'xyz789'}\n\n# Set cookies\nparser.set_cookie('new_session', 'newsess123')\nparser.set_cookie(admin='true', refresh='refresh123')\n\nprint(parser.get_cookies_as_header())\n# Output: session=abc123; user=john; token=xyz789; new_session=newsess123; admin=true; refresh=refresh123\n```\n\n---\n\n## CLI Usage\n\n### Parse Headers\n\n```bash\n# From file\n$ pyheaderparse parse -f headers.txt\n{\n  \"content-type\": {\"value\": \"application/json\", \"params\": {}},\n  \"content-length\": 1024,\n  \"user-agent\": \"Mozilla/5.0\"\n}\n\n# Get specific header\n$ pyheaderparse parse -f headers.txt --header user-agent\n\"Mozilla/5.0\"\n\n# From stdin\n$ cat headers.txt | pyheaderparse parse --stdin\n{\n  \"content-type\": {\"value\": \"application/json\", \"params\": {}},\n  ...\n}\n\n# Raw output format\n$ pyheaderparse parse -f headers.txt --format raw\ncontent-type: application/json\ncontent-length: 1024\nuser-agent: Mozilla/5.0\n```\n\n### Parse Cookies\n\n```bash\n# From full headers file\n$ pyheaderparse cookies -f headers.txt --full-headers\n{\n  \"session\": \"abc123\",\n  \"user\": \"john\",\n  \"token\": \"xyz789\"\n}\n\n# As Cookie header format\n$ pyheaderparse cookies -f headers.txt --full-headers --as-header\nsession=abc123; user=john; token=xyz789\n\n# Get specific cookie\n$ pyheaderparse cookies -f headers.txt --full-headers -c session\nabc123\n\n# From cookie-only file\n$ pyheaderparse cookies -f cookies.txt\n{\n  \"session\": \"abc123\",\n  \"user\": \"john\"\n}\n```\n\n### Show Header Info\n\n```bash\n$ pyheaderparse info -f headers.txt\n{\n  \"total_headers\": 15,\n  \"total_cookies\": 3,\n  \"content_type\": \"application/json\",\n  \"content_length\": 1024,\n  \"user_agent\": \"Mozilla/5.0\",\n  \"origin\": \"https://example.com\",\n  \"is_cors\": true,\n  \"sec_fetch\": {\n    \"site\": \"same-origin\",\n    \"mode\": \"cors\",\n    \"dest\": \"empty\",\n    \"user\": \"\"\n  },\n  \"client_hints\": {\n    \"sec-ch-ua\": [{\"brand\": \"Chrome\", \"version\": \"144\"}],\n    \"sec-ch-ua-mobile\": false,\n    \"sec-ch-ua-platform\": \"Windows\"\n  }\n}\n```\n\n---\n\n## API Reference\n\n### HeaderParser\n\n| Method/Property | Description | Example |\n|----------------|-------------|---------|\n| `HeaderParser(data?, **kwargs)` | Constructor | `HeaderParser(raw)` or `HeaderParser(content_type='json')` |\n| `parse(data?, **kwargs)` | Parse headers | `parser.parse(raw, accept='*/*')` |\n| `set(name?, value?, **kwargs)` | Set header(s) | `parser.set('Content-Type', 'json')` or `parser.set(accept='*/*')` |\n| `set_raw(name, value, **kwargs)` | Set without parsing | `parser.set_raw('X-Raw', 'value')` |\n| `get(name, default?)` | Get header (case-insensitive) | `parser.get('content-type')` |\n| `remove(*names)` | Remove headers | `parser.remove('x-custom', 'accept')` |\n| `clear()` | Clear all headers | `parser.clear()` |\n| `update(dict?, **kwargs)` | Update from dict/kwargs | `parser.update({'Accept': '*/*'}, dnt='1')` |\n| `to_dict(stringify?)` | Export as dictionary | `parser.to_dict()` or `parser.to_dict(stringify=True)` |\n| `to_raw()` | Export as raw format | `parser.to_raw()` |\n| `to_requests_headers()` | Export for requests lib | `requests.get(url, headers=parser.to_requests_headers())` |\n| `keys()` | Get header names | `parser.keys()` |\n| `values()` | Get header values | `parser.values()` |\n| `items()` | Get name-value pairs | `parser.items()` |\n| `cookies` | Access CookieParser | `parser.cookies.to_dict()` |\n| `get_cookie(name, default?)` | Get specific cookie | `parser.get_cookie('session')` |\n| `set_cookie(name?, value?, **kwargs)` | Set cookie(s) | `parser.set_cookie(session='abc')` |\n| `get_cookies_as_header()` | Cookies as header string | `parser.get_cookies_as_header()` |\n| `get_cookies_as_dict()` | Cookies as dictionary | `parser.get_cookies_as_dict()` |\n| `content_type` | Content-Type value | `parser.content_type` → `'application/json'` |\n| `content_length` | Content-Length as int | `parser.content_length` → `1024` |\n| `user_agent` | User-Agent value | `parser.user_agent` |\n| `origin` | Origin value | `parser.origin` |\n| `referer` | Referer value | `parser.referer` |\n| `is_cors()` | Check if CORS request | `parser.is_cors()` → `True/False` |\n| `is_ajax()` | Check if AJAX request | `parser.is_ajax()` → `True/False` |\n| `get_client_hints()` | Get Sec-CH-* headers | `parser.get_client_hints()` |\n| `get_sec_fetch_metadata()` | Get Sec-Fetch-* headers | `parser.get_sec_fetch_metadata()` |\n| `from_dict(dict)` | Create from dictionary | `HeaderParser.from_dict({'Content-Type': 'json'})` |\n| `from_kwargs(**kwargs)` | Create from kwargs | `HeaderParser.from_kwargs(content_type='json')` |\n| `from_requests_response(resp)` | Create from Response | `HeaderParser.from_requests_response(response)` |\n\n### CookieParser\n\n| Method | Description | Example |\n|--------|-------------|---------|\n| `CookieParser(data?, **kwargs)` | Constructor | `CookieParser(raw)` or `CookieParser(session='abc')` |\n| `parse(data?, **kwargs)` | Parse cookies | `cookies.parse(raw, extra='value')` |\n| `set(name?, value?, **kwargs)` | Set cookie(s) | `cookies.set('session', 'abc')` or `cookies.set(user='john')` |\n| `get(name, default?)` | Get specific cookie | `cookies.get('session')` |\n| `remove(*names)` | Remove cookies | `cookies.remove('session', 'token')` |\n| `clear()` | Clear all cookies | `cookies.clear()` |\n| `update(dict?, **kwargs)` | Update from dict/kwargs | `cookies.update({'a': '1'}, b='2')` |\n| `to_cookie_header(data?, **kwargs)` | Export as header string | `cookies.to_cookie_header()` → `'a=1; b=2'` |\n| `to_dict(data?, **kwargs)` | Export as dictionary | `cookies.to_dict()` → `{'a': '1', 'b': '2'}` |\n| `keys()` | Get cookie names | `cookies.keys()` |\n| `values()` | Get cookie values | `cookies.values()` |\n| `items()` | Get name-value pairs | `cookies.items()` |\n| `from_dict(dict)` | Create from dictionary | `CookieParser.from_dict({'session': 'abc'})` |\n| `from_kwargs(**kwargs)` | Create from kwargs | `CookieParser.from_kwargs(session='abc')` |\n\n### HeaderValue\n\n| Property/Method | Description | Example |\n|-----------------|-------------|---------|\n| `value` | Main header value | `hv.value` → `'text/html'` |\n| `params` | Parameter dictionary | `hv.params` → `{'charset': 'utf-8'}` |\n| `str(hv)` | String representation | `str(hv)` → `'text/html; charset=utf-8'` |\n\n---\n\n## Supported Headers\n\n### Standard Headers\n- `Content-Type`, `Content-Length`, `Content-Disposition`, `Content-Encoding`\n- `Accept`, `Accept-Language`, `Accept-Encoding`, `Accept-Charset`\n- `Cache-Control`, `Pragma`, `Expires`\n- `Authorization`, `WWW-Authenticate`, `Proxy-Authenticate`\n- `Cookie`, `Set-Cookie`\n- `User-Agent`, `Origin`, `Referer`, `Host`\n- `Location`, `Date`, `ETag`, `Last-Modified`\n\n### Security Headers\n- `DNT` (Do Not Track) → parsed as `bool`\n- `Sec-GPC` → parsed as `bool`\n- `Upgrade-Insecure-Requests` → parsed as `bool`\n\n### Client Hints (Sec-CH-UA-*)\n- `Sec-CH-UA` → parsed as list of `{'brand', 'version'}`\n- `Sec-CH-UA-Mobile` → parsed as `bool`\n- `Sec-CH-UA-Platform`, `Sec-CH-UA-Arch`, `Sec-CH-UA-Bitness`\n- `Sec-CH-UA-Model`, `Sec-CH-UA-Full-Version`, `Sec-CH-UA-Full-Version-List`\n- `Sec-CH-UA-Platform-Version`\n\n### Fetch Metadata (Sec-Fetch-*)\n- `Sec-Fetch-Site`, `Sec-Fetch-Mode`, `Sec-Fetch-Dest`, `Sec-Fetch-User`\n\n### Other\n- `Priority` → parsed as dict\n- `X-Requested-With`, `X-Forwarded-For`, `X-Real-IP`\n- Any custom headers (stored as strings)\n\n---\n\n## Error Handling\n\n```python\nfrom parser_header import HeaderParser, CookieParser\nfrom parser_header.exceptions import ParserError, InvalidHeaderError, EncodingError\n\n# Missing value error\ntry:\n    parser = HeaderParser()\n    parser.set('Content-Type')  # Missing value!\nexcept ValueError as e:\n    print(f\"Error: {e}\")\n    # Output: Error: value is required when name is provided\n\n# Key not found\ntry:\n    parser = HeaderParser()\n    value = parser['nonexistent']\nexcept KeyError as e:\n    print(f\"Error: {e}\")\n    # Output: Error: \"Header 'nonexistent' not found\"\n\n# Encoding error (rare)\ntry:\n    bad_bytes = b'\\xff\\xfe invalid'\n    parser = HeaderParser(bad_bytes)\nexcept EncodingError as e:\n    print(f\"Encoding failed: {e}\")\n```\n\n---\n\n## Development\n\n```bash\n# Clone repository\ngit clone https://github.com/cumulus13/pyheaderparse.git\ncd pyheaderparse\n\n# Install dev dependencies\npip install -e \".[dev]\"\n\n# Run tests\npytest\n\n# Run with coverage\npytest --cov=parser_header --cov-report=term-missing\n\n# Type checking\nmypy parser_header\n\n# Linting\nruff check parser_header\n\n# Format code\nblack parser_header\n```\n\n---\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file.\n\n## Author\n\n**Hadi Cahyadi** - cumulus13@gmail.com\n\n[![Buy Me a Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/cumulus13)\n\n[![Donate via Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/cumulus13)\n \n[Support me on Patreon](https://www.patreon.com/cumulus13)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcumulus13%2Fpyheaderparse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcumulus13%2Fpyheaderparse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcumulus13%2Fpyheaderparse/lists"}