Why requests?
Python includes a built-in urllib module for working with HTTP, but its syntax is cumbersome and unintuitive. The requests library solves this problem by providing an elegant and intuitive interface. No wonder its slogan is "HTTP for Humans".
Installation
Setting up requests is easy:
pip install requestsBasics: GET requests
Let's start with the most common type of request — GET. Let's imagine that we need to get data about a GitHub user:
import requests
response = requests.get('https://api.github.com/users/octocat')
# Checking the status of the response
print(response.status_code) # 200
# Getting JSON
data = response.json()
print(data['name']) # The Octocat
print(data['public_repos']) # Number of public repositoriesThe response object contains all the information about the server response: status code, headers, response body, and much more.

Request parameters
APIs often require passing parameters in the URL. The requests library allows you to do this elegantly:
# Search for repositories on GitHub
params = {
'q': 'python requests',
'sort': 'stars',
'order': 'desc'
}
response = requests.get('https://api.github.com/search/repositories', params=params)
repos = response.json()
for repo in repos['items'][:5]:
print(f"{repo['name']}: {repo['stargazers_count']} stars")The library automatically generates the correct URL with parameters, escaping special characters.
POST requests and sending data
POST requests are used to create resources or send forms. Let's consider an example with sending JSON:
# Creating a new resource
data = {
'title': 'I'm studying requests',
'body': 'This is a very convenient library!',
'userId': 1
}
response = requests.post('https://jsonplaceholder.typicode.com/posts', json=data)
if response.status_code == 201:
print('Resource created!')
print(response.json())Pay attention to the json parameter — requests automatically serializes the dictionary in JSON and sets the correct Content-Type header.
Working with headings
Many APIs require authentication through headers. Here's how it's done:
headers = {
'Authorization': 'Bearer YOUR_TOKEN_HERE',
'User-Agent': 'MyApp/1.0'
}
response = requests.get('https://api.example.com/data', headers=headers)Some APIs use API keys:
headers = {'X-API-Key': 'your_api_key'}
response = requests.get('https://api.example.com/protected', headers=headers)
Error handling
Professional work with the API is impossible without proper error handling:
try:
response = requests.get('https://api.example.com/data', timeout=5)
response.raise_for_status() # Throws an exception for 4xx and 5xx codes
data = response.json()
except requests.exceptions.HTTPError as http_err:
print(f'HTTP error: {http_err}')
except requests.exceptions.ConnectionError:
print('Connection error')
except requests.exceptions.Timeout:
print('Timeout')
except requests.exceptions.RequestException as err:
print(f'An error occurred: {err}')The raise_for_status() method automatically throws an exception if the server returned an error code.
Sessions for multiple requests
If you need to make multiple requests to the same API, use sessions. They save cookies and the connection, which significantly speeds up the work:
session = requests.Session()
session.headers.update({'Authorization': 'Bearer TOKEN'})
# All requests within the session will use common headers
response1 = session.get('https://api.example.com/users')
response2 = session.get('https://api.example.com/posts')
response3 = session.post('https://api.example.com/comments', json={'text': 'Hello'})
session.close()It is even better to use the context manager:
with requests.Session() as session:
session.headers.update({'Authorization': 'Bearer TOKEN'})
response = session.get('https://api.example.com/data')File management
Uploading files via the API is also easy:
# File upload
files = {'file': open('document.pdf', 'rb')}
response = requests.post('https://api.example.com/upload', files=files)
# Downloading file
response = requests.get('https://example.com/image.jpg', stream=True)
with open('image.jpg', 'wb') as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)The stream=True parameter allows you to load large files in batches without loading them completely into memory.
Practical example: working with the weather API
Let's create a full-fledged weather app:
import requests
def get_weather(city, api_key):
"""Gets the current weather for the specified city"""
base_url = "http://api.openweathermap.org/data/2.5/weather"
params = {
'q': city,
'appid': api_key,
'units': 'metric',
'lang': 'ru'
}
try:
response = requests.get(base_url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
weather_info = {
'city': data['name'],
'temperature': data['main']['temp'],
'feels': data['main']['feels_like'],
'description': data['weather'][0]['description'],
'Humidity': data['main']['humidity'],
'Wind': data['wind']['speed']
}
return weather_info
except requests.exceptions.RequestException as e:
print(f"Error retrieving data: {e}")
return None
# Use
weather = get_weather('Moscow', 'YOUR_API_KEY')
if weather:
print(f"Weather in the city {weather['city']}:"
print(f"Temperature: {weather['temperature']}°C")
print(f"Feels like: {weather['ощущается']}°C" print(f"Description: {weather['description']}"]}")Advanced options
Retry mechanism using adapters:
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
session = requests.Session()
retry = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
response = session.get('https://api.example.com/data')Working with authentication:
# Basic Auth
response = requests.get('https://api.example.com/data',
auth=('username', 'password'))
# OAuth 2.0 usually via headers
headers = {'Authorization': f'Bearer {access_token}'}
response = requests.get('https://api.example.com/data', headers=headers)Conclusion
The requests library makes working with the API in Python a pleasure. Simple and intuitive syntax, powerful features, and excellent documentation make it the de facto standard for HTTP requests in Python. By mastering requests, you will be able to integrate thousands of different services into your projects and create truly powerful applications.
Appendix Code offers structured courses in Python, JavaScript, API, and more. Interactive lessons, practical tasks and step-by-step learning will help you become a developer.
Join our Telegram channel, where you will find support from experienced developers, useful materials and answers to any questions about programming. Learn at a comfortable pace with a community of like-minded people!
