APIs REST são a principal forma de integrar sistemas e acessar dados externos — CRMs, ERPs, plataformas de e-commerce, dados governamentais. A biblioteca requests é o padrão de mercado em Python para consumir APIs HTTP: simples, poderosa e bem documentada.
Instalação
pip install requests pandas
GET básico
import requests
import pandas as pd
# Requisição simples:
resp = requests.get("https://api.exemplo.com/vendas")
print(resp.status_code) # 200 = OK
print(resp.json()) # converte JSON para dict/list Python
# Com parâmetros de query (?ano=2026®iao=sul):
resp = requests.get(
"https://api.exemplo.com/vendas",
params={"ano": 2026, "regiao": "sul"}
)
Autenticação
import os
TOKEN = os.environ.get("API_TOKEN")
# Bearer token (o mais comum):
headers = {"Authorization": f"Bearer {TOKEN}"}
resp = requests.get("https://api.exemplo.com/dados", headers=headers)
# API Key no header:
headers = {"X-API-Key": TOKEN}
# Basic Auth:
resp = requests.get(url, auth=("usuario", "senha"))
Tratamento de erros HTTP
resp = requests.get("https://api.exemplo.com/dados", headers=headers)
# raise_for_status() lança HTTPError para 4xx/5xx:
try:
resp.raise_for_status()
dados = resp.json()
except requests.exceptions.HTTPError as e:
print(f"Erro HTTP {resp.status_code}: {e}")
except requests.exceptions.ConnectionError:
print("Falha de conexão — sem rede ou servidor indisponível")
except requests.exceptions.Timeout:
print("A requisição excedeu o tempo limite")
except requests.exceptions.RequestException as e:
print(f"Erro na requisição: {e}")
POST: enviando dados
payload = {
"cliente": "Empresa ABC",
"valor": 12500,
"produto": "Licença Pro"
}
resp = requests.post(
"https://api.exemplo.com/pedidos",
json=payload, # serializa dict para JSON e define Content-Type
headers=headers
)
resp.raise_for_status()
pedido_criado = resp.json()
print(f"Pedido criado: ID {pedido_criado['id']}")
Paginação: coletando todos os registros
todos = []
pagina = 1
while True:
resp = requests.get(
"https://api.exemplo.com/vendas",
params={"page": pagina, "per_page": 100},
headers=headers
)
resp.raise_for_status()
dados = resp.json()
registros = dados.get("data", [])
if not registros:
break # sem mais páginas
todos.extend(registros)
pagina += 1
# Proteção contra loops infinitos:
if pagina > dados.get("total_pages", 999):
break
df = pd.DataFrame(todos)
print(f"Total de registros coletados: {len(df)}")
Session: reutilizando conexão e headers
# Session mantém headers e cookies automaticamente entre requisições:
with requests.Session() as s:
s.headers.update({"Authorization": f"Bearer {TOKEN}"})
s.headers.update({"Accept": "application/json"})
vendas = s.get("https://api.exemplo.com/vendas").json()
clientes = s.get("https://api.exemplo.com/clientes").json()
Perguntas frequentes
Como lidar com rate limiting (429 Too Many Requests)?
Use time.sleep() entre requisições ou implemente backoff exponencial com a biblioteca tenacity: @retry(wait=wait_exponential(min=1, max=60), stop=stop_after_attempt(5)).
requests vs httpx: quando usar cada um?
requests é síncrono — adequado para scripts e pipelines sequenciais. httpx com asyncio é para cenários onde você precisa fazer dezenas/centenas de chamadas em paralelo e cada milissegundo conta.