Python
requests library
HTTP headers
get method
programming tutorial

Using headers with the Python requests library's get method

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When you call requests.get, headers are passed as a plain Python dictionary. That sounds simple, but the real value is understanding which headers belong on a GET request, how to set them consistently, and how to inspect what was actually sent when an API rejects the request.

Basic Header Usage

The headers argument accepts key-value pairs.

python
1import requests
2
3headers = {
4    "User-Agent": "my-app/1.0",
5    "Accept": "application/json"
6}
7
8response = requests.get("https://api.github.com", headers=headers, timeout=10)
9print(response.status_code)

This is the standard pattern. requests takes care of serializing the header dictionary into the outgoing HTTP request.

Common Headers on GET Requests

Typical GET headers include:

  • 'Accept to express the response format you want'
  • 'Authorization for bearer tokens or other credentials'
  • 'User-Agent to identify the client'
  • 'If-None-Match or If-Modified-Since for caching and conditional requests'

Example with a bearer token:

python
1import requests
2
3headers = {
4    "Accept": "application/json",
5    "Authorization": "Bearer example-token"
6}
7
8response = requests.get("https://api.example.com/users", headers=headers, timeout=10)
9print(response.json())

For a GET request, you usually do not need Content-Type unless the API documentation specifically asks for it. Content-Type describes the body you are sending, and ordinary GET requests do not have one.

Using a Session for Repeated Headers

If several requests share the same headers, use a Session instead of rebuilding the same dictionary repeatedly.

python
1import requests
2
3session = requests.Session()
4session.headers.update({
5    "User-Agent": "inventory-sync/2.0",
6    "Accept": "application/json"
7})
8
9response1 = session.get("https://api.example.com/items", timeout=10)
10response2 = session.get("https://api.example.com/orders", timeout=10)
11
12print(response1.status_code, response2.status_code)

This is especially useful for authenticated clients where the same token or API version header is sent on every request.

Per-Request Overrides

Request-specific headers can still override session defaults.

python
1import requests
2
3session = requests.Session()
4session.headers.update({
5    "Accept": "application/json",
6    "User-Agent": "my-client/1.0"
7})
8
9response = session.get(
10    "https://api.example.com/export",
11    headers={"Accept": "text/csv"},
12    timeout=10
13)
14
15print(response.headers.get("Content-Type"))

That lets you keep common headers in one place while changing only the exceptions.

Inspect What Was Actually Sent

When a server behaves unexpectedly, inspect the prepared request rather than guessing.

python
1import requests
2
3request = requests.Request(
4    "GET",
5    "https://api.example.com/users",
6    headers={"Accept": "application/json", "X-Debug": "true"}
7)
8
9prepared = request.prepare()
10print(prepared.headers)

If you are using a session:

python
1import requests
2
3session = requests.Session()
4session.headers.update({"User-Agent": "my-client/1.0"})
5
6request = requests.Request("GET", "https://api.example.com/users", headers={"Accept": "application/json"})
7prepared = session.prepare_request(request)
8print(prepared.headers)

This is a reliable way to see header merging and final casing behavior.

Be Careful with Sensitive Headers

Headers often carry tokens, cookies, or API keys. Do not print them casually in logs.

A safer debugging pattern is:

python
1safe_headers = {
2    "Accept": "application/json",
3    "User-Agent": "my-client/1.0"
4}
5
6print(safe_headers)

If authentication is failing, log the presence of an auth header, not the secret value itself.

Timeouts and Error Handling Still Matter

Headers do not change the need for robust request handling.

python
1import requests
2
3try:
4    response = requests.get(
5        "https://api.example.com/users",
6        headers={"Accept": "application/json"},
7        timeout=10
8    )
9    response.raise_for_status()
10    print(response.json())
11except requests.RequestException as exc:
12    print(f"request failed: {exc}")

That is a better production pattern than assuming the request succeeded because the headers looked correct.

Common Pitfalls

The most common mistake is sending Content-Type on a GET request and assuming it controls the response format. Usually Accept is the header that matters for that.

Another mistake is rebuilding identical header dictionaries for every request instead of using a session.

Developers also forget to inspect the prepared request and end up debugging the wrong assumption about what was actually sent.

Finally, do not log raw authorization tokens or cookies while debugging header issues. Header debugging should not become a credential leak.

Summary

  • Pass GET headers to requests.get as a dictionary through the headers argument.
  • Use Accept, Authorization, and User-Agent deliberately based on the API's requirements.
  • Prefer requests.Session when multiple requests share default headers.
  • Inspect prepared requests when header behavior is unclear.
  • Keep secrets out of logs and combine header usage with normal timeout and error handling.

Course illustration
Course illustration

All Rights Reserved.