Biblioteca Python Requests: Guia Completo de Requisições HTTP em Python
Updated on
Fazer requisições HTTP em Python usando o módulo embutido urllib é notoriamente complexo e verboso. Você precisa codificar parâmetros manualmente, lidar com objetos de resposta com múltiplas chamadas de métodos e escrever dezenas de linhas de código boilerplate apenas para enviar uma requisição simples a uma API. Essa complexidade desacelera o desenvolvimento e torna seu código mais difícil de manter.
A biblioteca Python requests elimina essa frustração ao fornecer uma API elegante e amigável para comunicação HTTP. Seja consumindo APIs REST, fazendo web scraping, enviando arquivos ou construindo scripts de automação, a biblioteca requests torna as operações HTTP intuitivas e diretas com apenas algumas linhas de código.
Neste guia abrangente, você aprenderá desde requisições GET e POST básicas até recursos avançados como autenticação, sessões, tratamento de erros e padrões reais de integração com APIs.
Instalando a Biblioteca Python Requests
A biblioteca requests não faz parte da biblioteca padrão do Python, então você precisa instalá-la separadamente usando pip:
pip install requestsPara usuários de conda:
conda install requestsDepois de instalada, você pode importá-la nos seus scripts Python:
import requestsPara verificar a instalação e checar a versão:
import requests
print(requests.__version__)Fazendo Requisições GET com Python Requests
Requisições GET são o método HTTP mais comum, usado para recuperar dados de servidores. A biblioteca requests torna as requisições GET incrivelmente simples.
Requisição GET Básica
Veja como fazer uma requisição GET básica:
import requests
response = requests.get('https://api.github.com')
print(response.status_code) # 200
print(response.text) # Response body as stringRequisição GET com Parâmetros de Query
Em vez de construir URLs manualmente com query strings, use o parâmetro params:
import requests
# Method 1: Using params dictionary
params = {
'q': 'python requests',
'sort': 'stars',
'order': 'desc'
}
response = requests.get('https://api.github.com/search/repositories', params=params)
# The URL is automatically constructed:
# https://api.github.com/search/repositories?q=python+requests&sort=stars&order=desc
print(response.url) # View the constructed URL
data = response.json() # Parse JSON responseRequisição GET com Headers Personalizados
Muitas APIs exigem headers personalizados para autenticação ou negociação de conteúdo:
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.9'
}
response = requests.get('https://api.example.com/data', headers=headers)
print(response.json())Fazendo Requisições POST em Python
Requisições POST enviam dados para um servidor, comumente usadas para envios de formulários e operações de API.
Requisição POST com Dados de Formulário
Para enviar dados codificados como formulário (como envios de formulários HTML):
import requests
# Send form data
data = {
'username': 'john_doe',
'password': 'secret123',
'remember_me': True
}
response = requests.post('https://example.com/login', data=data)
print(response.status_code)Requisição POST com Payload JSON
APIs REST modernas geralmente esperam payloads JSON. A biblioteca requests lida com a serialização JSON automaticamente:
import requests
# Method 1: Using json parameter (recommended)
payload = {
'name': 'New Project',
'description': 'A test project',
'tags': ['python', 'api']
}
response = requests.post('https://api.example.com/projects', json=payload)
# Method 2: Manual JSON encoding
import json
headers = {'Content-Type': 'application/json'}
response = requests.post(
'https://api.example.com/projects',
data=json.dumps(payload),
headers=headers
)Requisição POST com Arquivos
Faça upload de arquivos usando o parâmetro files:
import requests
# Upload a single file
files = {'file': open('report.pdf', 'rb')}
response = requests.post('https://example.com/upload', files=files)
# Upload multiple files
files = {
'file1': open('document.pdf', 'rb'),
'file2': open('image.jpg', 'rb')
}
response = requests.post('https://example.com/upload', files=files)
# Upload file with additional form data
files = {'file': open('data.csv', 'rb')}
data = {'description': 'Monthly report', 'category': 'finance'}
response = requests.post('https://example.com/upload', files=files, data=data)Outros Métodos HTTP: PUT, PATCH, DELETE
A biblioteca requests suporta todos os métodos HTTP padrão:
import requests
# PUT - Replace entire resource
data = {'name': 'Updated Name', 'status': 'active'}
response = requests.put('https://api.example.com/users/123', json=data)
# PATCH - Partially update resource
data = {'status': 'inactive'}
response = requests.patch('https://api.example.com/users/123', json=data)
# DELETE - Remove resource
response = requests.delete('https://api.example.com/users/123')
print(response.status_code) # 204 No Content
# HEAD - Get headers only (no response body)
response = requests.head('https://example.com')
print(response.headers)
# OPTIONS - Get supported methods
response = requests.options('https://api.example.com/users')
print(response.headers.get('Allow'))Entendendo o Objeto Response
O objeto Response contém todas as informações sobre a resposta do servidor:
import requests
response = requests.get('https://api.github.com/users/github')
# Status code
print(response.status_code) # 200, 404, 500, etc.
# Response body as string
print(response.text)
# Response body as JSON (for JSON APIs)
data = response.json()
print(data['login'])
# Raw binary content (for images, files)
image_data = response.content
with open('profile.jpg', 'wb') as f:
f.write(image_data)
# Response headers
print(response.headers)
print(response.headers['Content-Type'])
# Encoding
print(response.encoding) # 'utf-8'
# Request information
print(response.request.headers)
print(response.request.url)
# Check if request was successful
if response.ok: # True if status_code < 400
print("Success!")Trabalhando com Headers de Requisição
Headers carregam metadados importantes sobre a requisição:
Definindo Headers Personalizados
import requests
headers = {
'User-Agent': 'MyApp/1.0',
'Accept': 'application/json',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
'Custom-Header': 'custom-value'
}
response = requests.get('https://api.example.com', headers=headers)Acessando Headers de Resposta
import requests
response = requests.get('https://api.github.com')
# Dictionary-like access
print(response.headers['Content-Type'])
print(response.headers.get('X-RateLimit-Remaining'))
# Case-insensitive access
print(response.headers['content-type']) # Works!
# Iterate all headers
for key, value in response.headers.items():
print(f"{key}: {value}")Autenticação com Python Requests
A biblioteca requests suporta múltiplos mecanismos de autenticação:
Autenticação Básica
import requests
from requests.auth import HTTPBasicAuth
# Method 1: Using auth parameter (recommended)
response = requests.get(
'https://api.example.com/protected',
auth=('username', 'password')
)
# Method 2: Explicit HTTPBasicAuth
response = requests.get(
'https://api.example.com/protected',
auth=HTTPBasicAuth('username', 'password')
)
# Method 3: Manual header (not recommended)
import base64
credentials = base64.b64encode(b'username:password').decode('utf-8')
headers = {'Authorization': f'Basic {credentials}'}
response = requests.get('https://api.example.com/protected', headers=headers)Autenticação com Bearer Token
Comum para tokens JWT e OAuth 2.0:
import requests
token = 'your_access_token_here'
headers = {'Authorization': f'Bearer {token}'}
response = requests.get('https://api.example.com/user', headers=headers)Autenticação com Chave de API (API Key)
import requests
# Method 1: Query parameter
params = {'api_key': 'your_api_key_here'}
response = requests.get('https://api.example.com/data', params=params)
# Method 2: Custom header
headers = {'X-API-Key': 'your_api_key_here'}
response = requests.get('https://api.example.com/data', headers=headers)Autenticação OAuth 2.0
Para OAuth 2.0, use a biblioteca requests-oauthlib:
from requests_oauthlib import OAuth2Session
client_id = 'your_client_id'
client_secret = 'your_client_secret'
token_url = 'https://oauth.example.com/token'
oauth = OAuth2Session(client_id)
token = oauth.fetch_token(token_url, client_secret=client_secret)
# Make authenticated requests
response = oauth.get('https://api.example.com/protected')Sessões para Conexões Persistentes
Sessões mantêm cookies, connection pooling e configurações entre múltiplas requisições:
import requests
# Create a session
session = requests.Session()
# Set headers for all requests in this session
session.headers.update({
'User-Agent': 'MyApp/1.0',
'Accept': 'application/json'
})
# Login and session maintains cookies
login_data = {'username': 'john', 'password': 'secret'}
session.post('https://example.com/login', data=login_data)
# Subsequent requests use the session cookies
response1 = session.get('https://example.com/dashboard')
response2 = session.get('https://example.com/profile')
# Close the session
session.close()Sessão com Autenticação
import requests
session = requests.Session()
session.auth = ('username', 'password')
# All requests in this session use the authentication
response1 = session.get('https://api.example.com/users')
response2 = session.get('https://api.example.com/posts')Session Context Manager
import requests
with requests.Session() as session:
session.headers.update({'Authorization': 'Bearer token123'})
response1 = session.get('https://api.example.com/data')
response2 = session.post('https://api.example.com/data', json={'key': 'value'})
# Session automatically closed after with blockEstratégias de Timeout e Retry
Sempre defina timeouts para evitar que requisições fiquem travadas indefinidamente:
Definindo Timeouts
import requests
# Single timeout value (applies to both connect and read)
response = requests.get('https://api.example.com', timeout=5)
# Separate connect and read timeouts
response = requests.get('https://api.example.com', timeout=(3, 10))
# 3 seconds to establish connection, 10 seconds to read response
# No timeout (dangerous - may hang forever)
response = requests.get('https://api.example.com', timeout=None)Implementando Lógica de Retry
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
# Configure retry strategy
retry_strategy = Retry(
total=3, # Total number of retries
backoff_factor=1, # Wait 1, 2, 4 seconds between retries
status_forcelist=[429, 500, 502, 503, 504], # Retry on these status codes
allowed_methods=["HEAD", "GET", "OPTIONS", "POST"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)
# Requests will automatically retry on failure
response = session.get('https://api.example.com/data')Tratamento de Erros em Python Requests
Um tratamento de erros robusto é crucial para aplicações em produção:
Tratando Exceções Comuns
import requests
from requests.exceptions import (
ConnectionError,
Timeout,
HTTPError,
RequestException
)
try:
response = requests.get('https://api.example.com/data', timeout=5)
response.raise_for_status() # Raises HTTPError for 4xx/5xx status codes
data = response.json()
except ConnectionError:
print("Failed to connect to the server")
except Timeout:
print("Request timed out")
except HTTPError as e:
print(f"HTTP error occurred: {e}")
print(f"Status code: {e.response.status_code}")
except RequestException as e:
# Catches all requests exceptions
print(f"An error occurred: {e}")
except ValueError:
# JSON decoding error
print("Invalid JSON response")Verificando Status Codes
import requests
response = requests.get('https://api.example.com/data')
# Method 1: Manual check
if response.status_code == 200:
data = response.json()
elif response.status_code == 404:
print("Resource not found")
elif response.status_code >= 500:
print("Server error")
# Method 2: Using raise_for_status()
try:
response.raise_for_status()
data = response.json()
except requests.exceptions.HTTPError as e:
if response.status_code == 404:
print("Resource not found")
elif response.status_code == 401:
print("Authentication required")
else:
print(f"HTTP error: {e}")
# Method 3: Using response.ok
if response.ok: # True if status_code < 400
data = response.json()
else:
print(f"Request failed with status {response.status_code}")Verificação SSL e Certificados
Por padrão, requests verifica certificados SSL:
import requests
# Default behavior - verify SSL certificate
response = requests.get('https://api.example.com')
# Disable SSL verification (not recommended for production)
response = requests.get('https://example.com', verify=False)
# Suppress the InsecureRequestWarning
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
response = requests.get('https://example.com', verify=False)
# Use custom CA bundle
response = requests.get('https://example.com', verify='/path/to/ca_bundle.crt')
# Client-side certificates
response = requests.get(
'https://example.com',
cert=('/path/to/client.crt', '/path/to/client.key')
)Usando Proxies com Python Requests
Configure servidores proxy para requisições:
import requests
# HTTP and HTTPS proxies
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
}
response = requests.get('https://api.example.com', proxies=proxies)
# SOCKS proxy (requires requests[socks])
proxies = {
'http': 'socks5://user:pass@host:port',
'https': 'socks5://user:pass@host:port'
}
# Use environment variables
# Set HTTP_PROXY and HTTPS_PROXY environment variables
response = requests.get('https://api.example.com') # Automatically uses env proxies
# Disable proxies
response = requests.get('https://api.example.com', proxies={'http': None, 'https': None})Comparação de Bibliotecas HTTP em Python
Veja como a biblioteca requests se compara com alternativas:
| Feature | requests | urllib | httpx | aiohttp |
|---|---|---|---|---|
| Ease of Use | Excellent (Pythonic API) | Poor (verbose) | Excellent | Good |
| Async Support | No | No | Yes | Yes |
| HTTP/2 Support | No | No | Yes | No |
| Session Management | Built-in | Manual | Built-in | Built-in |
| JSON Handling | Automatic | Manual | Automatic | Automatic |
| Connection Pooling | Yes | No | Yes | Yes |
| Standard Library | No (pip install) | Yes | No (pip install) | No (pip install) |
| Documentation | Excellent | Good | Excellent | Good |
| Performance | Good | Fair | Excellent | Excellent (async) |
| SSL/TLS | Full support | Full support | Full support | Full support |
| Best For | Synchronous HTTP, general use | Simple scripts, no dependencies | Modern sync/async HTTP | High-performance async |
Quando usar cada uma:
- requests: Escolha padrão para a maioria das operações HTTP síncronas. Melhor para web scraping, consumo de APIs e tarefas HTTP gerais.
- urllib: Apenas quando você não pode instalar pacotes externos (exigência de biblioteca padrão).
- httpx: Quando você precisa de suporte a HTTP/2 ou quer uma API moderna compatível com requests com capacidades async.
- aiohttp: Para aplicações assíncronas de alto desempenho lidando com muitas requisições concorrentes.
Rate Limiting e Scraping Responsável
Ao fazer scraping de sites ou chamar APIs, implemente rate limiting:
import requests
import time
from datetime import datetime
class RateLimitedSession:
def __init__(self, requests_per_second=1):
self.session = requests.Session()
self.min_interval = 1.0 / requests_per_second
self.last_request_time = 0
def get(self, url, **kwargs):
# Wait if necessary
elapsed = time.time() - self.last_request_time
if elapsed < self.min_interval:
time.sleep(self.min_interval - elapsed)
# Make request
response = self.session.get(url, **kwargs)
self.last_request_time = time.time()
return response
# Use rate-limited session
session = RateLimitedSession(requests_per_second=2) # 2 requests per second
urls = ['https://api.example.com/item/1', 'https://api.example.com/item/2']
for url in urls:
response = session.get(url)
print(f"{datetime.now()}: {response.status_code}")Respeitando o robots.txt
import requests
from urllib.robotparser import RobotFileParser
def can_fetch(url, user_agent='MyBot'):
"""Check if URL can be scraped according to robots.txt"""
rp = RobotFileParser()
robots_url = f"{url.split('/')[0]}//{url.split('/')[2]}/robots.txt"
rp.set_url(robots_url)
rp.read()
return rp.can_fetch(user_agent, url)
url = 'https://example.com/page'
if can_fetch(url):
response = requests.get(url)
else:
print("Scraping not allowed by robots.txt")Exemplos Reais e Casos de Uso
Exemplo 1: Consumindo uma API REST
import requests
class GitHubAPI:
def __init__(self, token=None):
self.base_url = 'https://api.github.com'
self.session = requests.Session()
if token:
self.session.headers.update({'Authorization': f'token {token}'})
def get_user(self, username):
"""Get user information"""
response = self.session.get(f'{self.base_url}/users/{username}')
response.raise_for_status()
return response.json()
def search_repositories(self, query, sort='stars', limit=10):
"""Search repositories"""
params = {'q': query, 'sort': sort, 'per_page': limit}
response = self.session.get(f'{self.base_url}/search/repositories', params=params)
response.raise_for_status()
return response.json()['items']
def create_issue(self, owner, repo, title, body):
"""Create an issue in a repository"""
url = f'{self.base_url}/repos/{owner}/{repo}/issues'
data = {'title': title, 'body': body}
response = self.session.post(url, json=data)
response.raise_for_status()
return response.json()
# Usage
api = GitHubAPI(token='your_github_token')
user = api.get_user('torvalds')
print(f"Name: {user['name']}, Followers: {user['followers']}")
repos = api.search_repositories('python requests', limit=5)
for repo in repos:
print(f"{repo['full_name']}: {repo['stargazers_count']} stars")Exemplo 2: Baixando Arquivos com Progresso
import requests
from tqdm import tqdm
def download_file(url, filename):
"""Download file with progress bar"""
response = requests.get(url, stream=True)
response.raise_for_status()
total_size = int(response.headers.get('content-length', 0))
with open(filename, 'wb') as f, tqdm(
desc=filename,
total=total_size,
unit='B',
unit_scale=True,
unit_divisor=1024,
) as progress_bar:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
progress_bar.update(len(chunk))
# Download a file
download_file('https://example.com/large-file.zip', 'downloaded.zip')Exemplo 3: Web Scraping com Tratamento de Erros
import requests
from bs4 import BeautifulSoup
import time
def scrape_articles(base_url, max_pages=5):
"""Scrape article titles from a news website"""
session = requests.Session()
session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
articles = []
for page in range(1, max_pages + 1):
try:
url = f"{base_url}?page={page}"
response = session.get(url, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
titles = soup.find_all('h2', class_='article-title')
for title in titles:
articles.append({
'title': title.text.strip(),
'url': title.find('a')['href'] if title.find('a') else None
})
print(f"Scraped page {page}: {len(titles)} articles")
time.sleep(1) # Rate limiting
except requests.exceptions.RequestException as e:
print(f"Error scraping page {page}: {e}")
continue
return articles
# Usage
articles = scrape_articles('https://news.example.com/articles', max_pages=3)
print(f"Total articles collected: {len(articles)}")Exemplo 4: Integração de API com Paginação
import requests
def fetch_all_items(api_url, headers=None):
"""Fetch all items from a paginated API"""
items = []
page = 1
while True:
try:
params = {'page': page, 'per_page': 100}
response = requests.get(api_url, params=params, headers=headers, timeout=10)
response.raise_for_status()
data = response.json()
if not data: # No more items
break
items.extend(data)
print(f"Fetched page {page}: {len(data)} items")
page += 1
# Check for pagination in headers
if 'Link' in response.headers:
links = response.headers['Link']
if 'rel="next"' not in links:
break
except requests.exceptions.RequestException as e:
print(f"Error fetching page {page}: {e}")
break
return items
# Usage
all_items = fetch_all_items('https://api.example.com/items')
print(f"Total items: {len(all_items)}")Testando APIs no Jupyter com RunCell
Ao desenvolver e testar integrações com APIs, o RunCell (opens in a new tab) fornece um ambiente de agente com IA diretamente em notebooks Jupyter. Em vez de depurar manualmente requisições e respostas HTTP, o agente inteligente do RunCell pode ajudar você a:
- Construir e testar automaticamente requisições de API com a autenticação correta
- Depurar parsing de resposta e tratamento de erros em tempo real
- Gerar trechos de código para padrões HTTP comuns
- Validar respostas de API contra schemas esperados
- Iterar rapidamente em transformações de dados a partir de respostas de API
Isso é particularmente valioso ao trabalhar com APIs complexas que exigem múltiplas etapas de autenticação, tratamento de paginação ou lógica de parsing de dados mais intrincada. O RunCell acelera o fluxo de desenvolvimento ao reduzir o vai-e-volta de testar requisições HTTP manualmente.
FAQ
Para que serve a biblioteca requests do Python?
A biblioteca requests do Python é usada para fazer requisições HTTP para servidores web e APIs. Ela simplifica tarefas como buscar páginas web, consumir APIs REST, enviar dados de formulário, fazer upload de arquivos e lidar com autenticação. É a biblioteca HTTP mais popular em Python devido à sua API intuitiva e ao conjunto abrangente de recursos.
Como instalo a biblioteca requests do Python?
Instale a biblioteca requests usando pip: pip install requests. Para ambientes conda, use conda install requests. Depois de instalada, importe-a com import requests no seu código Python. A biblioteca não faz parte da biblioteca padrão do Python, então a instalação é necessária.
Qual é a diferença entre requests.get() e requests.post()?
requests.get() recupera dados de um servidor sem modificar nada, normalmente usada para buscar páginas web ou dados de APIs. requests.post() envia dados ao servidor para criar ou atualizar recursos, comumente usada para envios de formulários, upload de arquivos ou operações de API que modificam o estado do servidor. Requisições GET passam parâmetros na URL, enquanto requisições POST enviam dados no corpo da requisição.
Como faço o tratamento de erros com a biblioteca requests do Python?
Use blocos try-except para capturar exceções de requisição: ConnectionError para problemas de rede, Timeout para respostas lentas, HTTPError para status codes 4xx/5xx e RequestException como captura geral. Chame response.raise_for_status() após cada requisição para levantar automaticamente HTTPError quando a requisição falhar. Sempre defina timeouts para evitar que requisições fiquem travadas indefinidamente.
Como envio dados JSON com Python requests?
Use o parâmetro json em requests: requests.post(url, json=data). A biblioteca serializa automaticamente dicionários Python para JSON e define o header Content-Type: application/json. Para fazer o parsing de respostas JSON, use response.json(), que desserializa o corpo da resposta JSON em um dicionário Python.
Devo usar requests ou urllib em Python?
Use a biblioteca requests para a maioria das operações HTTP. Ela oferece uma API mais limpa, tratamento automático de JSON, gerenciamento de sessão embutido e melhor tratamento de erros em comparação ao urllib. Só use urllib quando você não puder instalar pacotes externos e precisar depender apenas da biblioteca padrão do Python. Para aplicações modernas que exigem HTTP/2 ou suporte async, considere httpx como alternativa.
Como adiciono autenticação no Python requests?
Para autenticação Basic, use requests.get(url, auth=('username', 'password')). Para tokens Bearer (JWT, OAuth), adicione um header Authorization: headers = {'Authorization': f'Bearer {token}'}. Para API keys, adicione-as como parâmetros de query usando o dicionário params ou como headers personalizados como 'X-API-Key'. Sessões podem persistir a autenticação entre múltiplas requisições.
O que são sessões (sessions) em Python requests e quando devo usá-las?
Sessions mantêm configurações (headers, cookies, autenticação) entre múltiplas requisições para o mesmo servidor. Use sessions quando fizer múltiplas requisições a uma API, quando precisar manter estado de login com cookies, ou quando quiser reutilizar conexões TCP para melhor desempenho. Crie uma sessão com session = requests.Session() e use session.get() em vez de requests.get().
Conclusão
A biblioteca Python requests é uma ferramenta indispensável para comunicação HTTP em Python. Sua API elegante transforma operações HTTP complexas em código simples e legível. De requisições GET básicas a recursos avançados como autenticação, sessões, upload de arquivos e tratamento de erros, requests fornece tudo o que você precisa para interações HTTP robustas.
Ao dominar os padrões e as boas práticas deste guia — definir timeouts, implementar lógica de retry, tratar erros com elegância e respeitar rate limits — você construirá aplicações confiáveis que se comunicam de forma eficaz com serviços web e APIs. Seja consumindo APIs REST, fazendo web scraping ou criando ferramentas de automação, a biblioteca requests torna as operações HTTP diretas e fáceis de manter.