Voltar ao Glossario
Glossario Python

Requests: O que É e Como Funciona | Python Brasil

Aprenda a usar Requests em Python: requisicoes HTTP, GET, POST, headers, autenticacao, sessoes e boas praticas para consumir APIs e servicos web.

O que e Requests?

Requests e a biblioteca HTTP mais popular do Python, projetada para tornar requisicoes web simples e elegantes. Com o lema “HTTP for Humans”, ela abstrai a complexidade do protocolo HTTP, oferecendo uma API intuitiva para enviar requisicoes GET, POST, PUT, DELETE e outros metodos. Requests e usada por milhoes de projetos para consumir APIs REST, fazer web scraping, automatizar interacoes com servicos web e muito mais.

Embora o Python tenha o modulo embutido urllib, Requests e vastamente preferida pela comunidade por sua simplicidade e poder.

Instalacao e Primeiro Uso

# Instalacao
# pip install requests

import requests

# Requisicao GET simples
response = requests.get('https://api.github.com')
print(response.status_code)    # 200
print(response.headers['content-type'])  # application/json
print(response.json())         # dicionario Python
print(response.text)           # conteudo como string

Metodos HTTP

import requests

BASE_URL = 'https://jsonplaceholder.typicode.com'

# GET — buscar dados
response = requests.get(f'{BASE_URL}/posts/1')
post = response.json()
print(post['title'])

# GET com parametros de query
response = requests.get(f'{BASE_URL}/posts', params={'userId': 1, '_limit': 5})
print(response.url)  # .../posts?userId=1&_limit=5
posts = response.json()

# POST — criar dados
novo_post = {
    'title': 'Meu Post',
    'body': 'Conteudo do post',
    'userId': 1,
}
response = requests.post(f'{BASE_URL}/posts', json=novo_post)
print(response.status_code)  # 201
print(response.json())

# PUT — atualizar dados (completo)
atualizado = {'title': 'Titulo Atualizado', 'body': 'Novo conteudo', 'userId': 1}
response = requests.put(f'{BASE_URL}/posts/1', json=atualizado)

# PATCH — atualizar dados (parcial)
response = requests.patch(f'{BASE_URL}/posts/1', json={'title': 'Novo Titulo'})

# DELETE — remover dados
response = requests.delete(f'{BASE_URL}/posts/1')
print(response.status_code)  # 200

Headers e Autenticacao

import requests

# Headers customizados
headers = {
    'Authorization': 'Bearer meu_token_aqui',
    'Content-Type': 'application/json',
    'Accept-Language': 'pt-BR',
    'User-Agent': 'MinhaApp/1.0',
}
response = requests.get('https://api.exemplo.com/dados', headers=headers)

# Autenticacao basica
response = requests.get(
    'https://api.exemplo.com/privado',
    auth=('usuario', 'senha'),
)

# Autenticacao com token Bearer
response = requests.get(
    'https://api.exemplo.com/dados',
    headers={'Authorization': 'Bearer meu_token'},
)

Tratamento de Erros

import requests
from requests.exceptions import (
    ConnectionError, Timeout, HTTPError, RequestException
)

def buscar_dados(url: str) -> dict | None:
    """Busca dados de uma URL com tratamento de erros."""
    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()  # gera HTTPError se status >= 400
        return response.json()

    except Timeout:
        print('A requisicao excedeu o tempo limite')
    except ConnectionError:
        print('Falha na conexao com o servidor')
    except HTTPError as e:
        print(f'Erro HTTP: {e.response.status_code}')
        if e.response.status_code == 404:
            print('Recurso nao encontrado')
        elif e.response.status_code == 500:
            print('Erro interno do servidor')
    except RequestException as e:
        print(f'Erro na requisicao: {e}')

    return None

# Verificacao manual de status
response = requests.get('https://api.exemplo.com/dados')
if response.ok:  # True se status < 400
    dados = response.json()
else:
    print(f'Erro: {response.status_code} - {response.reason}')

Sessoes

Sessoes permitem reutilizar configuracoes e manter cookies entre requisicoes.

import requests

# Usando sessao para reutilizar configuracoes
session = requests.Session()
session.headers.update({
    'Authorization': 'Bearer meu_token',
    'User-Agent': 'MinhaApp/1.0',
})

# Todas as requisicoes da sessao herdam os headers
response1 = session.get('https://api.exemplo.com/usuarios')
response2 = session.get('https://api.exemplo.com/produtos')

# Sessao como context manager
with requests.Session() as s:
    # Login
    s.post('https://site.com/login', data={'user': 'ana', 'pass': 'senha'})
    # Requisicoes autenticadas (cookies mantidos)
    perfil = s.get('https://site.com/perfil')
    pedidos = s.get('https://site.com/pedidos')

Upload e Download de Arquivos

import requests
from pathlib import Path

# Upload de arquivo
with open('documento.pdf', 'rb') as f:
    response = requests.post(
        'https://api.exemplo.com/upload',
        files={'arquivo': ('documento.pdf', f, 'application/pdf')},
    )

# Download de arquivo pequeno
response = requests.get('https://exemplo.com/imagem.png')
Path('imagem.png').write_bytes(response.content)

# Download de arquivo grande (streaming)
with requests.get('https://exemplo.com/video.mp4', stream=True) as r:
    r.raise_for_status()
    with open('video.mp4', 'wb') as f:
        for chunk in r.iter_content(chunk_size=8192):
            f.write(chunk)

Retry e Resiliencia

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def criar_sessao_resiliente(
    retries: int = 3,
    backoff_factor: float = 0.3,
    status_forcelist: tuple = (500, 502, 503, 504),
) -> requests.Session:
    """Cria sessao com retry automatico."""
    session = requests.Session()
    retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
    )
    adapter = HTTPAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    return session

# Usar
session = criar_sessao_resiliente()
response = session.get('https://api.exemplo.com/dados')

Erros Comuns

O erro mais perigoso e nao definir timeout nas requisicoes, o que pode fazer o programa travar indefinidamente aguardando resposta de um servidor que nao responde. Outro erro e nao verificar o status da resposta, assumindo que toda requisicao foi bem-sucedida. Tambem e comum nao usar sessoes quando se faz multiplas requisicoes ao mesmo servidor, perdendo o beneficio de reutilizacao de conexoes TCP. Enviar dados sensiveis como tokens em URLs (query params) em vez de headers e um problema de seguranca frequente.

Boas Praticas

Sempre defina timeout em todas as requisicoes. Use response.raise_for_status() para tratar erros HTTP. Use sessoes para multiplas requisicoes ao mesmo servidor. Implemente retry com backoff exponencial para resiliencia. Nunca inclua credenciais diretamente no codigo — use variaveis de ambiente. Para APIs assincronas, considere httpx como alternativa que suporta async/await.

Quando Usar

Requests e ideal para consumir APIs REST, fazer web scraping, automatizar interacoes com servicos web e qualquer operacao que envolva requisicoes HTTP sincronas. Para aplicacoes assincronas de alta concorrencia, considere aiohttp ou httpx. Para testes, responses ou httpx.MockTransport permitem simular respostas HTTP.