Introduction to Python requests Library
The Python programming language has become a powerful tool for various
applications, from web development to data science. One area where
Python shines is its ability to work with web services and APIs, and the
requests library is arguably the most widely used tool for this
purpose. This article aims to provide a comprehensive guide to the
Python requests library, from installation to advanced use-cases.
What is the requests Library?
The requests library is a Python module that allows you to send all
kinds of HTTP requests—GET, POST, PUT, DELETE, and more—in an extremely
simple and intuitive manner. With just a few lines of code, you can
retrieve web pages, submit forms, or interact with
RESTful
APIs. Developed by Kenneth Reitz, requests abstracts many of the
complexities involved with sending HTTP requests, making it easier for
Python developers to interact with the internet.
Why use requests over urllib?
While Python’s Standard Library comes with the urllib module to handle
HTTP requests, many find it cumbersome and less user-friendly. Here are
some reasons why you might prefer requests over urllib:
- Ease of Use:
requestsoffers a more straightforward API for sending HTTP requests and takes care of many tasks automatically, making it easier to use. - JSON Support: The
requestslibrary provides built-in JSON support, making it easier to work with JSON APIs. - Session Handling: Managing sessions (a series of requests to the same server) is simplified, allowing you to persist cookies and headers across multiple requests.
- Connection Timeouts: requests allows you to specify connection timeouts, giving you better control over your code’s execution time.
- Community Support: Given its popularity, you are more likely to
find community-contributed plugins and tutorials that work
specifically with the
requestslibrary, making it easier to find help when you need it.
Installation and Setup
Getting started with the requests library is remarkably easy, thanks to Python’s package manager, pip. Below are the steps to install and verify the library.
To install the requests library, open your terminal or command prompt
and run the following command:
pip install requests
If you’re using Python 3.x and pip points to an older Python version,
you may need to use pip3 instead:
pip3 install requests
Once the installation is complete, it’s good practice to verify that the
library is properly installed and accessible from your Python
environment. To do this, open a Python interpreter by typing python or
python3 in the terminal, and then try to import the requests module:
import requests
If you don’t encounter any errors, then the installation was successful.
You can also check the installed version of requests with the
following code:
print(requests.__version__)
This will output the version of the requests library that is currently
installed, e.g., 2.25.1.
Understanding the Basic Concepts
Before diving into the code and making HTTP requests with Python
requests library, it’s essential to understand some of the basic
concepts surrounding HTTP methods, URLs, headers, and parameters.
HTTP methods: GET, POST, PUT, DELETE
HTTP methods determine the type of action you want to perform when
making an HTTP request. The four primary methods you will most likely
interact with when using the Python requests library are GET, POST,
PUT, and DELETE.
GET: This method retrieves data from a specified resource.
response = requests.get('https://jsonplaceholder.typicode.com/todos/1')
POST: This method sends data to a server to create a resource.
payload = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://httpbin.org/post', data=payload)
PUT: This method updates a current resource with new data.
payload = {'key1': 'new_value1', 'key2': 'new_value2'}
response = requests.put('https://httpbin.org/put', data=payload)
DELETE: This method removes a specified resource.
response = requests.delete('https://httpbin.org/delete')
Understanding URLs, Headers, and Parameters
URLs: The Uniform Resource Locator is the web address where your
desired resource resides. The Python requests library functions take
this as their primary argument.
url = 'https://jsonplaceholder.typicode.com/todos/1'
response = requests.get(url)
Headers: HTTP headers allow the client and the server to send additional information with the request or the response. For example, you can specify the type of response you want, like JSON.
headers = {'Accept': 'application/json'}
response = requests.get(url, headers=headers)
Parameters: These are extra data that you can send along with your GET request as query parameters in the URL.
payload = {'userId': 1}
response = requests.get('https://jsonplaceholder.typicode.com/todos', params=payload)
Making Your First Request
Once you have a grasp of the basic concepts, the next step is to start
making HTTP requests. This section will guide you through sending your
first GET and POST requests using Python requests library.
1. Sending a GET Request
A GET request is often used to retrieve data from a server. The following code shows how to send a simple GET request to an API endpoint that returns a TODO item as JSON:
import requests
# Define the URL for the GET request
url = 'https://jsonplaceholder.typicode.com/todos/1'
# Send the GET request
response = requests.get(url)
# Check if the request was successful
if response.status_code == 200:
print("Success:", response.json())
else:
print("Failed:", response.status_code)
# Output: Success: {'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}
The Python requests.get() function makes a GET request to the URL
specified and returns a Response object. You can inspect the object’s
properties like status_code to determine if the request was successful
and json() to get the JSON content.
2. Sending a POST Request
POST requests are used to send data to a server, typically to create a new resource or submit form data. Below is a Python code example that sends a POST request:
# Define the URL and payload
url = 'https://httpbin.org/post'
payload = {'username': 'john', 'password': '12345'}
# Send the POST request
response = requests.post(url, json=payload)
# Check if the request was successful
if response.status_code == 200:
print("Successfully posted data:", response.json())
else:
print("Failed to post data:", response.status_code)
# Output could be like: Successfully posted data: {'args': {}, 'data': '', 'files': {}, 'form': {'username': 'john', 'password': '12345'}, 'headers': {...}, 'json': None, 'origin': '...', 'url': 'https://httpbin.org/post'}
Here, requests.post() sends data as JSON to the server. The Response
object has the same properties as in the GET example.
Handling Responses
Once you’ve made a request, it’s crucial to understand how to handle the responses that you receive. This section will go through understanding status codes, reading the response content, and parsing JSON responses.
1. Understanding Status Codes
HTTP status codes are three-digit numbers that indicate the result of
your HTTP request. Commonly used status codes include 200 for success,
404 for not found, 400 for bad request, etc.
import requests
response = requests.get('https://jsonplaceholder.typicode.com/todos/1')
# Check the status code
status_code = response.status_code
if status_code == 200:
print("Request was successful.")
elif status_code == 404:
print("Resource not found.")
else:
print(f"An error occurred. HTTP Status Code: {status_code}")
2. Reading Response Content
The content of the HTTP response can be read using various methods, like
text to get the content as a string or content to get it as bytes.
# Get content as a string
text_content = response.text
print("Text Content:", text_content)
# Get content as bytes
byte_content = response.content
print("Byte Content:", byte_content)
3. Parsing JSON Responses
Often, APIs return responses in JSON format. The Python requests
library makes it incredibly easy to parse JSON responses using the
json() method on the Response object.
# Parse JSON response
json_content = response.json()
print("JSON Content:", json_content)
# Access individual fields
print("User ID:", json_content["userId"])
print("Title:", json_content["title"])
Here’s an example that combines all three aspects:
# Make a GET request
response = requests.get('https://jsonplaceholder.typicode.com/todos/1')
# Check status code
if response.status_code == 200:
print("Request was successful.")
# Read and print text content
print("Text Content:", response.text)
# Parse and print JSON content
json_content = response.json()
print("JSON Content:", json_content)
# Access and print individual fields
print("User ID:", json_content["userId"])
print("Title:", json_content["title"])
else:
print(f"An error occurred. HTTP Status Code: {response.status_code}")
Advanced Features
As you get more comfortable with the basics of the Python requests
library, you’ll want to explore some of the more advanced
functionalities it offers. This section will cover customizing request
headers, handling cookies, dealing with redirects, and setting timeouts.
1. Customizing Request Headers
Sometimes, you’ll need to include specific headers in your request, such
as an API key or a custom User-Agent string. You can do this using the
headers parameter.
# Define custom headers
headers = {'User-Agent': 'my-app', 'Authorization': 'Bearer <Your-API-Token>'}
# Make a GET request with custom headers
response = requests.get('https://some-api.com/data', headers=headers)
# Process response
if response.status_code == 200:
print("Data retrieved successfully.")
2. Handling Cookies
The Python requests library can also send and receive cookies. Cookies
are generally used for maintaining user sessions or tracking user
behavior.
# Define a URL
url = 'https://some-website.com/login'
# Data that needs to be sent
payload = {'username': 'user', 'password': 'pass'}
# Make a POST request to set cookies
response = requests.post(url, data=payload)
# Extract cookies
cookies = response.cookies
# Make another request using the cookies
response = requests.get('https://some-website.com/dashboard', cookies=cookies)
3. Redirects and Following Links
By default, the Python requests library follows HTTP redirects.
However, you can control this behavior using the allow_redirects
parameter.
# Make a request without following redirects
response = requests.get('https://some-website.com/redirect', allow_redirects=False)
# Check if it's a redirect
if response.status_code == 302:
print("This is a redirect. The new URL is:", response.headers['Location'])
4. Handling Timeouts
You can set timeouts to ensure that your request doesn’t hang
indefinitely. The timeout parameter can be used to specify how long
the request should wait to connect and receive data.
# Make a GET request with a timeout of 5 seconds
try:
response = requests.get('https://some-api.com/data', timeout=5)
except requests.exceptions.Timeout:
print("The request timed out.")
else:
if response.status_code == 200:
print("Data retrieved successfully.")
# If the request takes longer than 5 seconds to connect or receive data, a Timeout exception will be raised.
Parameters and Payloads
Often, you’ll need to send additional data along with your HTTP
requests, whether it’s search queries for a GET request or form data for
a POST request. The Python requests library makes it easy to send such
data using parameters and payloads.
1. Sending URL Parameters
URL parameters are typically sent in GET requests to filter or customize
the data you’re requesting. These are the key=value pairs you often
see in URLs. You can send these using the params keyword argument.
# Define URL and parameters
url = 'https://some-api.com/search'
parameters = {'query': 'python', 'limit': 10}
# Send GET request with URL parameters
response = requests.get(url, params=parameters)
# Check response
if response.status_code == 200:
print(f"Search results: {response.json()}")
2. Sending Payload in POST Requests
When you want to create or update resources on the server, you’ll typically use a POST request with a payload. The payload usually contains the data you want to send, in the form of a dictionary, list, or JSON.
# Define URL and payload
url = 'https://some-api.com/create'
payload = {'name': 'John', 'age': 30}
# Send POST request with payload
response = requests.post(url, json=payload)
# Check response
if response.status_code == 201:
print(f"Resource created: {response.json()}")
3. Uploading Files
Sometimes you’ll need to upload files like images, PDFs, or text files
to a server. You can do this using the files keyword argument in a
POST request.
# Define URL and files to upload
url = 'https://some-api.com/upload'
files = {'file': ('myfile.txt', open('myfile.txt', 'rb'))}
# Send POST request with file
response = requests.post(url, files=files)
# Check response
if response.status_code == 200:
print(f"File uploaded successfully: {response.json()}")
Sessions and Persistent Connections
HTTP is a stateless protocol, which means each request is independent
and contains all the information needed for processing. However, many
applications require a level of statefulness to track user data across
multiple interactions. That’s where HTTP sessions come in, and Python
requests library provides an easy way to manage these sessions.
1. What is a Session?
An HTTP session is a sequence of network request-response transactions.
In the context of the requests library, a session is an instance of
the Session class. It allows you to persist certain parameters like
headers and cookies across multiple requests, reducing redundant code
and making your code more efficient.
2. Creating and Managing Sessions
Creating a session is simple; you instantiate the Session class and
then use that session object for subsequent requests. Here’s a basic
example:
# Importing requests module
import requests
# Create a session
s = requests.Session()
# Add headers to the session
s.headers.update({'user-agent': 'my-app'})
# Perform a GET request
response = s.get('https://some-api.com/resource')
# Perform another GET request, this one will use the same headers as the first one
another_response = s.get('https://some-api.com/another-resource')
# Close the session
s.close()
In this example, we first create a session object and set its headers. Then, we perform two GET requests. Both will use the headers we set on the session object. This is useful if you’re interacting with an API that requires authentication via headers, as you only need to set them once for the session.
Error Handling
Even with well-constructed API calls, you’re likely to encounter errors
at some point. These could be client errors (like 404 Not Found) or
server errors (like 500 Internal Server Error). It’s crucial to
implement robust error-handling routines to manage these gracefully.
1. Handling HTTP Errors
The simplest way to check for HTTP errors is to use the
response.raise_for_status() method, which will raise an HTTPError if
the HTTP request returned an unsuccessful status code. Here’s a basic
example:
import requests
try:
response = requests.get('https://some-api.com/resource')
response.raise_for_status() # Will raise an HTTPError if the HTTP request returned an unsuccessful status code
except requests.HTTPError as err:
print(f"An HTTP error occurred: {err}")
2. Raising Custom Exceptions
Sometimes, you’ll want to raise your own exceptions based on the content
of the response or some other condition. This is useful when dealing
with APIs that return a 200 OK status code but include the actual
error message in the response body.
response = requests.get('https://some-api.com/resource')
data = response.json()
if "error" in data:
raise ValueError(f"API returned an error: {data['error']}")
3. Debugging Failed Requests
When things go wrong, you’ll want to gather as much information as
possible to debug the issue. Python requests library provides multiple
ways to do this:
Response Content: The first thing to check is the content of the
response object using response.content or response.text.
print(response.content)
Response Headers: Sometimes the headers contain useful debugging
information. These can be accessed with response.headers.
print(response.headers)
Logs: For even more details, you can enable logging in Python to get information on what requests is doing under the hood.
import logging
logging.basicConfig(level=logging.DEBUG)
Authentication
A common requirement for interacting with web services is
authentication. The Python requests library provides built-in
mechanisms for several types of authentication, as well as the
flexibility to handle any custom schemes you might encounter.
1. Basic Authentication
Basic authentication is one of the oldest and most straightforward
methods of HTTP authentication. The Python requests library makes
basic authentication easy.
Example:
import requests
from requests.auth import HTTPBasicAuth
response = requests.get('https://api.example.com/resource', auth=HTTPBasicAuth('username', 'password'))
# Alternatively, you can use a simpler syntax
response = requests.get('https://api.example.com/resource', auth=('username', 'password'))
2. OAuth
OAuth (Open Authorization) is a more modern authentication scheme and is
commonly used for token-based authentication. While requests itself
doesn’t provide built-in OAuth support, you can use an OAuth library or
manually set the Authorization header.
Example using manually set headers:
headers = {'Authorization': 'Bearer YOUR_ACCESS_TOKEN'}
response = requests.get('https://api.example.com/resource', headers=headers)
3. Custom Authentication
Sometimes, you may need to implement a custom authentication mechanism
that isn’t supported out of the box by requests. In such cases, you
can subclass requests.auth.AuthBase to create your custom
authentication scheme.
Example:
from requests.auth import AuthBase
class CustomAuth(AuthBase):
def __call__(self, request):
# Implement your custom authentication here
request.headers['X-Custom-Auth'] = 'my-auth-token'
return request
# Usage
auth_instance = CustomAuth()
response = requests.get('https://api.example.com/resource', auth=auth_instance)
In this example, we define a custom authentication class CustomAuth
that sets a header X-Custom-Auth. We then pass an instance of this
class to the requests.get() method via the auth parameter.
Advanced Use-cases
After mastering the basics, you can leverage the Python requests
library for more advanced scenarios like web scraping, asynchronous
requests, and streaming large files or datasets.
1. Web Scraping with requests
Web scraping involves downloading web pages and extracting information
from them. Below is a simple example where we scrape the title of a
webpage using requests and BeautifulSoup.
import requests
from bs4 import BeautifulSoup
response = requests.get('https://example.com')
soup = BeautifulSoup(response.text, 'html.parser')
title_tag = soup.find('title')
print(f'Title of the web page is: {title_tag.string if title_tag else "not found"}')
2. Asynchronous Requests
While Python requests itself is synchronous, you can achieve
asynchronous behavior by using Python’s asyncio library along with
aiohttp.
import aiohttp
import asyncio
async def fetch_url(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
loop = asyncio.get_event_loop()
result = loop.run_until_complete(fetch_url('https://example.com'))
3. Streaming Large Files or Datasets
Downloading large files or datasets can be efficiently done using
requests by streaming the data.
response = requests.get('https://example.com/large-file', stream=True)
with open('large_file', 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
In this example, we set stream=True to ensure that only a chunk of the
file is fetched at a time into memory. We then save these chunks into a
file called large_file.
Performance Considerations
When working on projects that involve a high volume of HTTP requests, it’s essential to consider performance aspects like speed and memory usage. Below are some points on how to measure and optimize performance.
1. Benchmarking requests vs Other Libraries
You can compare the performance of Python requests with other HTTP
libraries using Python’s built-in timeit module or similar
benchmarking tools. Here’s a simple example to compare requests and
http.client.
import requests
import http.client
import timeit
def fetch_with_requests():
requests.get('https://www.example.com')
def fetch_with_http_client():
conn = http.client.HTTPSConnection("www.example.com")
conn.request("GET", "/")
conn.getresponse()
print("Requests Library:", timeit.timeit(fetch_with_requests, number=100))
print("HTTP.client:", timeit.timeit(fetch_with_http_client, number=100))
Sample Output:
Requests Library: 2.123456
HTTP.client: 1.789012
This sample output indicates that http.client is a bit faster for this
specific task, although Python requests offers many more features and
is easier to use.
2. Optimizing Your Requests
requests provides several features that allow you to optimize your
HTTP requests for better performance.
Using Sessions for Multiple Requests
For making several Python requests to the same host, using a Session object can improve performance by reusing the underlying TCP connection.
with requests.Session() as session:
session.get('https://www.example.com/page1')
session.get('https://www.example.com/page2')
Limiting Redirection
By limiting redirection, you can avoid unnecessary HTTP requests.
response = requests.get('https://www.example.com', allow_redirects=False)
Comparison with Other Libraries
Comparing Python requests with other libraries like urllib,
http.client, and third-party options can be a useful exercise to
understand their relative strengths and weaknesses. Whether to use a
table or a descriptive approach largely depends on the complexity and
variety of the features you’re comparing.
| Feature | requests |
urllib |
http.client |
Third-party Libraries |
|---|---|---|---|---|
| Ease of Use | High | Medium | Low | Varies |
| Redirect Handling | Built-in | Manual | Manual | Varies |
| Session Support | Yes | No | No | Varies |
| Timeout Handling | Built-in | Manual | Built-in | Varies |
| Custom Headers | Easy | Moderate | Difficult | Varies |
| Cookie Handling | Built-in | Manual | Manual | Varies |
| Community Support | High | High | Medium | Varies |
Here is a summary of the comparison:
- Ease of Use:
requestsshines in ease of use with simple syntax and methods for all kinds of HTTP actions.urllib, while comprehensive, often requires more code for the same tasks.http.clientis a lower-level library that offers less abstraction, making it more cumbersome for typical tasks. - Session Support:
requestsprovides a built-inSessionclass, making it simple to persist certain parameters across multiple requests. Neitherurllibnorhttp.clientoffer this feature out of the box. - Custom Headers and Redirects: All libraries allow custom headers,
but Python
requestsmakes this particularly easy. It also handles redirects automatically, while inurllibandhttp.client, you would typically have to manage this yourself.
Frequently Asked Questions
Why is the requests library preferred over urllib?
The requests library is often preferred due to its user-friendly
syntax and built-in methods for various HTTP actions, which makes it
more accessible and easier to use than urllib.
What do I do when I encounter a 404 error?
A 404 error indicates that the resource you’re trying to access doesn’t exist. Double-check the URL and any parameters you’ve added to the request.
How do I send data or parameters with my request?
Data or parameters can be sent in the request’s body or as URL parameters. The choice between the two largely depends on the API’s requirements.
Is it possible to make asynchronous requests with requests?
While the native requests library doesn’t support asynchronous
operations, you can use it in conjunction with Python’s asyncio or use
an alternative library like httpx for asynchronous requests.
How can I improve the speed of my requests?
Consider using a session to persist parameters and reuse HTTP connections. You can also adjust timeout settings and explore parallel requests for more speed.
What are the security concerns when using requests?
Always be cautious with sending sensitive information such as passwords. Use HTTPS whenever possible and consider additional layers of security like OAuth for authentication.
How do I handle cookies with requests?
The requests library makes it easy to send and receive cookies through
the cookies attribute of a response object or by using a session.
Can I integrate requests with my web scraping projects?
Absolutely. requests is often used in conjunction with web scraping
libraries like BeautifulSoup to fetch web pages for parsing.
How do I debug a failed request?
You can inspect the response object to check the status code, headers, and other meta-information to help diagnose what might have gone wrong.
Can I use requests for testing APIs?
Yes, requests is commonly used in API testing, often in combination
with testing frameworks like pytest.
Summary
In this comprehensive guide, we’ve walked you through the fundamentals
and advanced features of the Python requests library. Starting with
installation and basic HTTP methods, we delved into more complex topics
like custom headers, cookies, and even asynchronous requests.
Core Concepts:
- HTTP Methods:
GET,POST,PUT, andDELETEare the primary HTTP methods you’ll need to know. - Handling Responses: Knowing how to handle status codes and read response content is crucial for effective API interactions.
- Advanced Features: From customizing request headers to managing
sessions and cookies,
requestsoffers a wide array of functionalities. - Error Handling: Properly catching and handling errors can save a lot of debugging time and make your application more robust.
- Authentication:
requestssupports multiple methods of authentication, including Basic Auth and OAuth. - Performance: While
requestsis generally fast and efficient, you have options for optimizing performance, like reusing sessions.
Key Takeaways:
- The Python
requestslibrary is an indispensable tool for any Python developer working with HTTP requests or APIs. - It’s highly customizable, allowing you to tweak almost every aspect of your request process.
- Proper error handling is essential for building reliable apps.
- For specialized needs,
requestsworks well with other Python libraries and frameworks, proving its flexibility.
Additional Resources
For further information and advanced topics, please refer to the Official Documentation.
Thank you for reading, and we hope this guide serves as a valuable resource on your coding journey!


