Requests is the standard Python library for making HTTP requests. You use it to call web APIs, fetch pages, or upload data. It is simpler than the built-in urllib and is used everywhere in scripts and applications. This guide covers installation, basic GET, reading the response (text or JSON), query parameters and headers, error handling, and timeouts. For a short step-by-step recipe see the How-To make an HTTP GET request; you should know dictionaries and JSON when working with APIs.
1. When to use Requests
Use Requests whenever you need to send HTTP requests from Python: REST APIs, downloading files, form submissions, or checking a URL. For building your own API server use FastAPI or Flask. For browser automation use a different tool (e.g. Selenium). Requests is synchronous; for many concurrent requests consider concurrent.futures or async libraries. For most “call an API” tasks, Requests is the right choice.
2. Install and import
Requests is not in the standard library. Install it (e.g. in a virtual environment):
pip install requests
If you get ModuleNotFoundError: No module named 'requests', ensure the interpreter you run has Requests installed. Then:
import requests
3. Basic GET and response content
requests.get(url) returns a Response object. Use .status_code for the HTTP status (200, 404, 500), .text for the body as a string, and .json() to parse JSON (raises an error if the body is not valid JSON). The property .ok is True when the status is in the 200s. Always check the status or call response.raise_for_status() before assuming success.
response = requests.get("https://api.github.com")
print(response.status_code) # 200
print(response.text) # raw body
data = response.json() # parsed dict (if JSON)
4. Response object: headers, URL, encoding
response.headers is a dict-like object of response headers. response.url is the final URL after redirects. response.encoding is used to decode .text; you can set it if the server sent a wrong or missing charset. For binary content (e.g. images) use response.content. For more on headers and auth see Headers and Authentication.
print(response.headers.get("Content-Type"))
print(response.url)
print(response.encoding)
5. Query parameters and headers
Pass query parameters as a dict with params=; Requests encodes and appends them. Pass custom headers (e.g. API key, Accept) with headers=. This keeps URLs and headers separate from the logic and avoids manual encoding.
params = {"key": "value", "page": 1}
headers = {"Authorization": "Bearer TOKEN", "Accept": "application/json"}
response = requests.get("https://api.example.com/search", params=params, headers=headers)
6. Error handling and timeouts
Network calls can fail (timeout, connection error, DNS) or return 4xx/5xx. Use response.raise_for_status() to raise for bad status codes. Wrap in try/except for requests.exceptions.RequestException (or Timeout, HTTPError). Always set timeout= (seconds) so requests do not hang. For retries and finer control see the How-To set a timeout and retry HTTP requests.
try:
response = requests.get("https://api.example.com/data", timeout=5)
response.raise_for_status()
data = response.json()
except requests.exceptions.Timeout:
print("Request timed out")
except requests.exceptions.RequestException as e:
print("Request failed", e)
7. Best practices and next steps
Use timeouts on every request. Check status or use raise_for_status(). For multiple requests to the same host, use a requests.Session() for connection reuse and default headers. Respect rate limits and API terms of use. Next: GET and POST for POST and request bodies, Headers and Authentication for auth, and How to make an HTTP GET request for a concise recipe. When you see connection or JSON errors, check the Errors section.