---
title: "Requests: O que É e Como Funciona | Python Brasil"
url: "https://python.dev.br/glossario/requests/"
markdown_url: "https://python.dev.br/glossario/requests.MD"
description: "Aprenda a usar Requests em Python: requisicoes HTTP, GET, POST, headers, autenticacao, sessoes e boas praticas para consumir APIs e servicos web."
date: "2025-06-18"
author: ""
---

# 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

```python
# 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

```python
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

```python
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

```python
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.

```python
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

```python
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

```python
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.

> **Clientes HTTP em outras linguagens**: <a href="https://golang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'golang.com.br', content: 'glossario-requests'})">Go possui um cliente HTTP poderoso na biblioteca padrão</a>, e <a href="https://rustlang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'rustlang.com.br', content: 'glossario-requests'})">Rust com reqwest</a> oferece requisições HTTP assíncronas e tipadas.
