Consumindo APIs REST com Python — 2025 | Python Brasil
Aprenda a consumir APIs REST com Python e requests. GET, POST, autenticação e paginação. Comece agora!
APIs REST (Representational State Transfer) são a principal forma de comunicação entre sistemas na web moderna. Desde consultar a previsão do tempo até integrar sistemas de pagamento, consumir APIs é uma habilidade essencial para qualquer desenvolvedor Python. A biblioteca requests torna esse trabalho simples e intuitivo.
Neste artigo, vamos aprender a fazer requisições HTTP, trabalhar com autenticação, tratar erros de rede e construir integrações robustas com APIs externas.
Instalação e primeira requisição
A biblioteca requests é o padrão da comunidade Python para requisições HTTP:
# No terminal:
# pip install requests
import requests
# Requisição GET simples
resposta = requests.get("https://api.github.com")
print(f"Status: {resposta.status_code}")
print(f"Headers: {resposta.headers['content-type']}")
print(f"Dados: {resposta.json()}")
O objeto Response contém todas as informações da resposta: status code, headers, corpo e cookies. O método .json() converte automaticamente o corpo da resposta em um dicionário Python.
Métodos HTTP: GET, POST, PUT, DELETE
Cada método HTTP tem um propósito específico na interação com APIs:
import requests
BASE_URL = "https://jsonplaceholder.typicode.com"
# GET - Buscar dados
resposta = requests.get(f"{BASE_URL}/posts/1")
post = resposta.json()
print(f"Título: {post['title']}")
# GET com parâmetros de query
params = {"userId": 1, "_limit": 3}
resposta = requests.get(f"{BASE_URL}/posts", params=params)
posts = resposta.json()
print(f"\nPosts do usuário 1 (limite 3):")
for p in posts:
print(f" - {p['title'][:50]}...")
# POST - Criar dados
novo_post = {
"title": "Meu post via Python",
"body": "Conteúdo criado automaticamente com requests.",
"userId": 1
}
resposta = requests.post(f"{BASE_URL}/posts", json=novo_post)
print(f"\nPost criado - ID: {resposta.json()['id']}")
print(f"Status: {resposta.status_code}")
# PUT - Atualizar dados (substituição completa)
post_atualizado = {
"id": 1,
"title": "Título atualizado",
"body": "Corpo atualizado via Python.",
"userId": 1
}
resposta = requests.put(f"{BASE_URL}/posts/1", json=post_atualizado)
print(f"\nPost atualizado: {resposta.json()['title']}")
# PATCH - Atualização parcial
resposta = requests.patch(
f"{BASE_URL}/posts/1",
json={"title": "Apenas o título mudou"}
)
print(f"Título alterado: {resposta.json()['title']}")
# DELETE - Remover dados
resposta = requests.delete(f"{BASE_URL}/posts/1")
print(f"\nPost removido - Status: {resposta.status_code}")
A diferença entre json= e data= é importante: json= serializa automaticamente o dicionário para JSON e define o Content-Type correto, enquanto data= envia os dados como formulário.
Tratamento de erros e timeout
Requisições de rede podem falhar por diversos motivos. Um código robusto precisa tratar essas situações:
import requests
from requests.exceptions import (
ConnectionError, Timeout, HTTPError, RequestException
)
def fazer_requisicao(url, timeout=10):
"""Faz uma requisição GET com tratamento completo de erros."""
try:
resposta = requests.get(url, timeout=timeout)
resposta.raise_for_status() # Levanta exceção para status 4xx e 5xx
return resposta.json()
except ConnectionError:
print(f"Erro de conexão: não foi possível acessar {url}")
return None
except Timeout:
print(f"Timeout: o servidor não respondeu em {timeout} segundos")
return None
except HTTPError as e:
print(f"Erro HTTP {e.response.status_code}: {e.response.reason}")
return None
except RequestException as e:
print(f"Erro inesperado na requisição: {e}")
return None
# Testando
dados = fazer_requisicao("https://api.github.com/users/python")
if dados:
print(f"Usuário: {dados['login']}")
print(f"Repositórios públicos: {dados['public_repos']}")
O raise_for_status() é uma ferramenta valiosa: ele converte códigos de status HTTP 400-599 em exceções Python, permitindo que você os trate com try/except.
Autenticação
APIs protegidas exigem autenticação. Os métodos mais comuns são token Bearer e API keys:
import requests
# Autenticação com token Bearer (OAuth2)
token = "seu_token_aqui"
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/json"
}
resposta = requests.get(
"https://api.github.com/user",
headers=headers
)
# Autenticação com API key via header
headers = {"X-API-Key": "sua_chave_aqui"}
resposta = requests.get(
"https://api.exemplo.com/dados",
headers=headers
)
# Autenticação com API key via query parameter
params = {"api_key": "sua_chave_aqui", "cidade": "São Paulo"}
resposta = requests.get(
"https://api.exemplo.com/clima",
params=params
)
# Autenticação básica (usuário e senha)
resposta = requests.get(
"https://api.exemplo.com/admin",
auth=("usuario", "senha")
)
Sessões para múltiplas requisições
Quando você faz várias requisições para a mesma API, usar uma sessão é mais eficiente:
import requests
class ClienteAPI:
"""Cliente para consumir uma API REST."""
def __init__(self, base_url, token):
self.base_url = base_url
self.sessao = requests.Session()
self.sessao.headers.update({
"Authorization": f"Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json"
})
self.sessao.timeout = 15
def get(self, endpoint, params=None):
"""Faz uma requisição GET."""
url = f"{self.base_url}/{endpoint}"
resposta = self.sessao.get(url, params=params)
resposta.raise_for_status()
return resposta.json()
def post(self, endpoint, dados):
"""Faz uma requisição POST."""
url = f"{self.base_url}/{endpoint}"
resposta = self.sessao.post(url, json=dados)
resposta.raise_for_status()
return resposta.json()
def fechar(self):
"""Fecha a sessão."""
self.sessao.close()
# Uso:
# cliente = ClienteAPI("https://api.exemplo.com/v1", "meu_token")
# usuarios = cliente.get("usuarios", params={"page": 1})
# novo = cliente.post("usuarios", {"nome": "Ana", "email": "ana@email.com"})
# cliente.fechar()
Sessões reutilizam conexões TCP e mantêm cookies e headers entre requisições, o que melhora significativamente a performance.
Trabalhando com paginação
Muitas APIs retornam dados paginados. Veja como consumir todas as páginas:
import requests
def buscar_todos_repositorios(usuario):
"""Busca todos os repositórios de um usuário do GitHub."""
repositorios = []
pagina = 1
por_pagina = 100
while True:
resposta = requests.get(
f"https://api.github.com/users/{usuario}/repos",
params={"page": pagina, "per_page": por_pagina, "sort": "updated"},
timeout=10
)
resposta.raise_for_status()
dados = resposta.json()
if not dados:
break
repositorios.extend(dados)
pagina += 1
if len(dados) < por_pagina:
break
return repositorios
# Uso:
# repos = buscar_todos_repositorios("python")
# print(f"Total de repositórios: {len(repos)}")
# for repo in repos[:5]:
# print(f" {repo['name']} - {repo['stargazers_count']} estrelas")
Boas práticas ao consumir APIs
Para integrações robustas e profissionais:
- Sempre defina timeout: requisições sem timeout podem travar seu programa indefinidamente.
- Use
raise_for_status(): trate erros HTTP explicitamente em vez de verificar status codes manualmente. - Armazene credenciais de forma segura: use variáveis de ambiente, nunca hardcode tokens no código.
- Respeite rate limits: verifique os headers
X-RateLimit-*e implemente backoff quando necessário. - Use sessões: para múltiplas requisições ao mesmo servidor, sessões são mais eficientes.
- Faça cache quando possível: evite requisições desnecessárias armazenando respostas em cache.
- Documente as integrações: mantenha documentação sobre quais APIs são consumidas, endpoints usados e formatos esperados.
Conclusão
Consumir APIs REST com Python e requests é uma habilidade fundamental no desenvolvimento moderno. Praticamente todo sistema precisa se integrar com serviços externos, e a biblioteca requests torna esse processo simples e produtivo. Com tratamento adequado de erros, autenticação e boas práticas, suas integrações serão confiáveis e fáceis de manter.
Como próximos passos, explore a biblioteca httpx para requisições assíncronas, aprenda sobre GraphQL como alternativa ao REST e estude como criar suas próprias APIs com FastAPI ou Django REST Framework.
Equipe Python Brasil
Contribuidor do Python Brasil — Aprenda Python em Português