Python · API · Beginner

Headers and the Echo Endpoint

5 tasks

Add custom HTTP headers to requests and use the echo endpoint to inspect what you send.

HTTP headers

#
Every HTTP request carries metadata alongside its body: these are headers. Headers tell the server things like what kind of response you expect, who you are, and how to interpret the request body. To send custom headers with requests, pass a dict as the headers argument: ```python import requests BASE_URL = 'https://apilearn.tukas.dev' headers = { 'Accept': 'application/json', 'User-Agent': 'MyScript/1.0', } response = requests.get(f'{BASE_URL}/api/products/', headers=headers) ``` A few headers you will encounter often: - User-Agent — identifies your client. Servers sometimes log this or block unknown agents. requests sends a default like 'python-requests/2.x.x'. - Accept — tells the server what format you want back. For a JSON API this is usually 'application/json', though the server often ignores it and returns JSON regardless. - Content-Type — describes the format of the body you are sending (for POST/PUT/PATCH). requests sets this automatically when you use json=. - Authorization — carries authentication credentials. Covered in the auth topics. You can also read the headers that the server sent back: ```python response = requests.get(f'{BASE_URL}/api/products/') print(response.headers['Content-Type']) # application/json print(response.headers.get('X-Custom', '')) # '' if not present ``` response.headers is case-insensitive — 'content-type' and 'Content-Type' return the same value.

Using the echo endpoint

#
The echo endpoint mirrors your request back as JSON. It is designed for debugging — you can see exactly what the server received: ```python import requests BASE_URL = 'https://apilearn.tukas.dev' response = requests.get(f'{BASE_URL}/api/echo/') print(response.json()) ``` The response contains the method, path, headers, and body that the server saw. Now add a custom header and watch it appear: ```python headers = {'X-My-Header': 'hello', 'User-Agent': 'MyBot/1.0'} response = requests.get(f'{BASE_URL}/api/echo/', headers=headers) data = response.json() print(data['headers']['X-My-Header']) # 'hello' print(data['headers']['User-Agent']) # 'MyBot/1.0' ``` Send a POST with a JSON body and inspect it: ```python payload = {'action': 'test', 'value': 42} response = requests.post(f'{BASE_URL}/api/echo/', json=payload) data = response.json() print(data['method']) # 'POST' print(data['body']) # the payload you sent ``` When you use json=, requests automatically sets Content-Type to application/json and serializes the dict. You can confirm this through echo: ```python print(data['headers']['Content-Type']) # application/json ``` The echo endpoint also accepts arbitrary paths, which is useful to test how different URL shapes behave: ```python response = requests.get(f'{BASE_URL}/api/echo/debug/anything/you/want/') print(response.json()['path']) # '/api/echo/debug/anything/you/want/' ```

Headers and echo reference

#
Echo endpoints: ``` GET/POST/PUT/PATCH/DELETE /api/echo/ Mirror any request GET/POST/PUT/PATCH/DELETE /api/echo/{path} Mirror with arbitrary path ``` Echo response shape: ```json { "method": "POST", "path": "/api/echo/", "headers": { "Content-Type": "application/json", ... }, "body": { ... }, "query_params": { ... } } ``` Common request headers: ``` User-Agent Identifies your client Accept Expected response format (application/json) Content-Type Format of the request body (set auto by json=) Authorization Auth credentials (Token ..., Bearer ...) ``` Sending headers: ```python requests.get(url, headers={'X-Custom': 'value'}) requests.post(url, json=payload) # Content-Type set automatically ``` Reading response headers: ```python response.headers['Content-Type'] # direct access response.headers.get('X-Custom', '') # safe access with default ```
01

Inspect the echo response

#

Send a GET request to /api/echo/ and print the full JSON response. Notice which headers the server received from your default request.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

# Send GET to /api/echo/ and print the response JSON
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/echo/')
import json
print(json.dumps(response.json(), indent=2))
02

Send a custom header

#

Send a GET to /api/echo/ with a custom header X-Client-Name set to "my-script". Verify it appears in the echo response by printing its value from the response.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

# Add X-Client-Name header and verify it in the echo response
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

headers = {'X-Client-Name': 'my-script'}
response = requests.get(f'{BASE_URL}/api/echo/', headers=headers)
data = response.json()
print(data['headers']['X-Client-Name'])
03

Change the User-Agent

#

Send a request to /api/echo/ with User-Agent set to "DataCollector/2.0". Print the User-Agent value from the echo response to confirm it was received.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

# Set User-Agent and verify in echo
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

headers = {'User-Agent': 'DataCollector/2.0'}
response = requests.get(f'{BASE_URL}/api/echo/', headers=headers)
print(response.json()['headers']['User-Agent'])
04

POST with a JSON body

#

Send a POST to /api/echo/ with a JSON body containing keys "name" and "value". Print the method and body fields from the echo response.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

payload = {'name': 'test', 'value': 99}

# POST to /api/echo/ and print method and body from response
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

payload = {'name': 'test', 'value': 99}
response = requests.post(f'{BASE_URL}/api/echo/', json=payload)
data = response.json()
print(data['method'])
print(data['body'])
05

Read response headers

#

Fetch GET /api/products/ and print the Content-Type and any header that contains "Allow" in its name. If "Allow" is not present, print "Not found".

import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/products/')

# Print Content-Type and look for an Allow header
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/products/')

print(response.headers['Content-Type'])

allow = response.headers.get('Allow', 'Not found')
print(allow)