Python API & Requests
Working with APIs and making HTTP requests in Python
The Python requests
library is a powerful tool for making HTTP requests to web services and APIs.
It simplifies working with HTTP methods, handling responses, and managing authentication.
This guide covers the basics of making HTTP requests, working with APIs, handling responses, authentication methods, and best practices for API consumption.
Installation and Setup
The requests
library is not part of the Python standard library, so you'll need to install it:
pip install requests
# Import the library
import requests
Basic HTTP Requests
The requests
library provides simple methods for different HTTP methods:
import requests # GET request response = requests.get('https://api.example.com/data') # POST request response = requests.post('https://api.example.com/submit', data={'key': 'value'}) # PUT request response = requests.put('https://api.example.com/update', data={'key': 'new_value'}) # DELETE request response = requests.delete('https://api.example.com/delete') # HEAD request (only get headers) response = requests.head('https://api.example.com/data') # OPTIONS request response = requests.options('https://api.example.com')
URL Parameters
You can pass URL parameters (query string) in several ways:
# Method 1: Add parameters directly to URL response = requests.get('https://api.example.com/search?q=python&page=1') # Method 2: Use the params parameter (recommended) payload = { 'q': 'python', 'page': 1, 'sort': 'relevance' } response = requests.get('https://api.example.com/search', params=payload) # The URL becomes: https://api.example.com/search?q=python&page=1&sort=relevance print(response.url)
Working with Responses
After making a request, you can access various properties of the response:
import requests response = requests.get('https://api.github.com/users/python') # Status code print(f"Status code: {response.status_code}") # e.g., 200, 404, 500 # Check if request was successful if response.status_code == 200: print("Success!") elif response.status_code == 404: print("Not found!") # Alternative way to check for success if response.ok: # True if status_code is less than 400 print("Request was successful") # Response content print(response.text) # Raw text response # JSON response data = response.json() # Parse JSON response into a Python dictionary print(data['name']) # Response headers print(response.headers) print(response.headers['Content-Type']) # Response encoding print(response.encoding) # Response cookies print(response.cookies) # Response URL (useful for redirects) print(response.url) # Response history (list of redirects) print(response.history)
Error Handling
import requests try: response = requests.get('https://api.example.com/data', timeout=5) # Raise an exception if response was unsuccessful response.raise_for_status() # Process the successful response data = response.json() print(data) except requests.exceptions.HTTPError as errh: print(f"HTTP Error: {errh}") except requests.exceptions.ConnectionError as errc: print(f"Connection Error: {errc}") except requests.exceptions.Timeout as errt: print(f"Timeout Error: {errt}") except requests.exceptions.RequestException as err: print(f"Request Error: {err}") except ValueError as ve: print(f"JSON parsing failed: {ve}")
Sending Data
Form Data
# Send form data (application/x-www-form-urlencoded) form_data = { 'username': 'user123', 'password': 'securepassword', 'remember': True } response = requests.post('https://api.example.com/login', data=form_data) # Send multipart/form-data (for file uploads) files = { 'profile_image': open('image.jpg', 'rb') } form_data = { 'username': 'user123' } response = requests.post('https://api.example.com/upload', files=files, data=form_data)
JSON Data
# Send JSON data json_data = { 'name': 'John Doe', 'age': 30, 'hobbies': ['coding', 'reading'], 'is_active': True } response = requests.post('https://api.example.com/users', json=json_data) # Alternative: manually converting to JSON import json json_string = json.dumps(json_data) headers = {'Content-Type': 'application/json'} response = requests.post('https://api.example.com/users', data=json_string, headers=headers)
HTTP Headers
Customize HTTP headers for your requests:
# Custom headers
headers = {
'User-Agent': 'Python Requests Client/1.0',
'Authorization': 'Bearer your_access_token',
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Custom-Header': 'custom-value'
}
response = requests.get('https://api.example.com/data', headers=headers)
Authentication Methods
Basic Authentication
# Method 1: Using auth parameter response = requests.get('https://api.example.com/private', auth=('username', 'password')) # Method 2: Using the HTTPBasicAuth from requests.auth import HTTPBasicAuth response = requests.get('https://api.example.com/private', auth=HTTPBasicAuth('username', 'password'))
Token Authentication
# Bearer token authentication token = "your_access_token" headers = { 'Authorization': f'Bearer {token}' } response = requests.get('https://api.example.com/data', headers=headers) # API key in query parameters params = { 'api_key': 'your_api_key', 'q': 'search_term' } response = requests.get('https://api.example.com/search', params=params)
OAuth 2.0
For OAuth 2.0, you can use the requests-oauthlib
library:
# pip install requests-oauthlib from requests_oauthlib import OAuth2Session client_id = "your_client_id" client_secret = "your_client_secret" authorization_base_url = 'https://example.com/oauth/authorize' token_url = 'https://example.com/oauth/token' redirect_uri = 'https://your-app.com/callback' # Create OAuth session oauth = OAuth2Session(client_id, redirect_uri=redirect_uri) # Authorization URL authorization_url, state = oauth.authorization_url(authorization_base_url) print(f'Please go to {authorization_url} and authorize access') # Get authorization code from callback authorization_response = input('Enter the full callback URL: ') # Fetch token token = oauth.fetch_token(token_url, authorization_response=authorization_response, client_secret=client_secret) # Use the token to access protected resources response = oauth.get('https://example.com/api/resource')
Using Sessions
Sessions allow you to persist certain parameters across requests:
import requests # Create a session session = requests.Session() # Set persistent headers and cookies session.headers.update({ 'User-Agent': 'Python Requests Client/1.0', 'Accept': 'application/json' }) # Session automatically manages cookies across requests # Login and get cookies session.post('https://api.example.com/login', data={'username': 'user', 'password': 'pass'}) # All subsequent requests will include cookies and headers response = session.get('https://api.example.com/dashboard') # Add auth to the session session.auth = ('username', 'password') # Make authenticated requests response = session.get('https://api.example.com/protected') # Close the session when done session.close()
Advanced Features
Timeouts
# Set timeout in seconds (connection timeout, read timeout) response = requests.get('https://api.example.com/data', timeout=5) # 5 seconds # Different timeouts for connection and read response = requests.get('https://api.example.com/data', timeout=(3, 10)) # 3 seconds for connection, 10 seconds for reading
Streaming Responses
# For large files, use streaming to avoid loading the entire file into memory with requests.get('https://example.com/large-file.zip', stream=True) as response: # Check if the request was successful response.raise_for_status() # Write response to file in chunks with open('large-file.zip', 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk)
Proxies
# Using proxies proxies = { 'http': 'http://10.10.10.10:8000', 'https': 'http://10.10.10.10:8000', } response = requests.get('https://api.example.com/data', proxies=proxies) # With authentication proxies = { 'http': 'http://user:pass@10.10.10.10:8000', 'https': 'http://user:pass@10.10.10.10:8000', }
SSL Verification
# Disable SSL verification (not recommended for production) response = requests.get('https://api.example.com/data', verify=False) # Specify a local cert response = requests.get('https://api.example.com/data', verify='/path/to/certfile') # Client-side certificates response = requests.get('https://api.example.com/data', cert=('/path/to/client.cert', '/path/to/client.key'))
Best Practices
- Always use timeouts to prevent your application from hanging indefinitely.
- Handle errors properly using try/except blocks and response.raise_for_status().
- Use sessions for multiple requests to the same site.
- Secure sensitive data like API keys and tokens using environment variables or secure storage.
- Respect rate limits by implementing proper backoff strategies.
- Stream large responses to avoid memory issues.
- Keep SSL verification enabled in production environments.
- Add user agents to identify your application to the API provider.
Rate Limiting Example
import requests import time from requests.exceptions import RequestException def make_api_request(url, max_retries=3, backoff_factor=1): """Make API request with exponential backoff retry logic""" retries = 0 while retries <= max_retries: try: response = requests.get(url, timeout=10) # If we get a 429 Too Many Requests, back off and retry if response.status_code == 429: wait_time = backoff_factor * (2 ** retries) print(f"Rate limited. Retrying in {wait_time} seconds...") time.sleep(wait_time) retries += 1 continue # For other status codes, raise for status as usual response.raise_for_status() return response except RequestException as e: print(f"Request failed: {e}") if retries >= max_retries: print("Maximum retries exceeded.") raise wait_time = backoff_factor * (2 ** retries) print(f"Retrying in {wait_time} seconds...") time.sleep(wait_time) retries += 1 return None # Should not reach here due to raise above
Real-World Examples
GitHub API
import requests # Get user information from GitHub API def get_github_user(username): url = f"https://api.github.com/users/{username}" headers = { 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'PythonRequestsExample/1.0' } response = requests.get(url, headers=headers) if response.status_code == 200: return response.json() elif response.status_code == 404: return {"error": "User not found"} else: response.raise_for_status() # Get list of repositories for a user def get_user_repos(username): url = f"https://api.github.com/users/{username}/repos" headers = { 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'PythonRequestsExample/1.0' } response = requests.get(url, headers=headers) response.raise_for_status() return response.json() # Example usage try: user = get_github_user('python') print(f"User: {user['name']}") print(f"Bio: {user['bio']}") print(f"Followers: {user['followers']}") repos = get_user_repos('python') print(f"\nTotal repos: {len(repos)}") print("\nTop 5 repositories:") for repo in sorted(repos, key=lambda r: r['stargazers_count'], reverse=True)[:5]: print(f"- {repo['name']}: {repo['stargazers_count']} stars") except requests.exceptions.RequestException as e: print(f"Error: {e}")
Weather API
import requests import os # Get weather information from OpenWeatherMap API def get_weather(city, api_key): base_url = "https://api.openweathermap.org/data/2.5/weather" params = { 'q': city, 'appid': api_key, 'units': 'metric' # Use metric units (Celsius) } response = requests.get(base_url, params=params) response.raise_for_status() return response.json() # Example usage try: # Get API key from environment variable (best practice) api_key = os.getenv('OPENWEATHERMAP_API_KEY') if not api_key: print("Please set the OPENWEATHERMAP_API_KEY environment variable") exit(1) city = "London" weather_data = get_weather(city, api_key) temp = weather_data['main']['temp'] humidity = weather_data['main']['humidity'] description = weather_data['weather'][0]['description'] print(f"Weather in {city}:") print(f"Temperature: {temp}°C") print(f"Humidity: {humidity}%") print(f"Conditions: {description}") except requests.exceptions.RequestException as e: print(f"Error fetching weather data: {e}")
Practice Exercises
Try these exercises to strengthen your API and requests skills:
- Create a function to search for books using the Google Books API
- Build a simple command-line weather app using a weather API
- Write a script to download and save images from an image API
- Create a program that fetches and displays cryptocurrency prices
- Build a function to post updates to a social media platform API