Skip to content

Biblioteca Requests de Python: Guía completa de solicitudes HTTP en Python

Updated on

Hacer solicitudes HTTP en Python usando el módulo integrado urllib es famoso por ser complejo y verboso. Tienes que codificar parámetros manualmente, gestionar objetos de respuesta con múltiples llamadas a métodos y escribir decenas de líneas de código repetitivo solo para enviar una solicitud sencilla a una API. Esta complejidad ralentiza el desarrollo y hace que tu código sea más difícil de mantener.

La biblioteca requests de Python elimina esta frustración al proporcionar una API elegante y amigable para las personas para la comunicación HTTP. Ya sea que consumas APIs REST, hagas scraping de sitios web, subas archivos o construyas scripts de automatización, la biblioteca requests hace que las operaciones HTTP sean intuitivas y directas con solo unas pocas líneas de código.

En esta guía completa, aprenderás desde solicitudes GET y POST básicas hasta funciones avanzadas como autenticación, sesiones, manejo de errores y patrones reales de integración con APIs.

📚

Instalación de la biblioteca Requests de Python

La biblioteca requests no forma parte de la biblioteca estándar de Python, así que necesitas instalarla por separado usando pip:

pip install requests

Para usuarios de conda:

conda install requests

Una vez instalada, puedes importarla en tus scripts de Python:

import requests

Para verificar la instalación y comprobar la versión:

import requests
print(requests.__version__)

Hacer solicitudes GET con Python Requests

Las solicitudes GET son el método HTTP más común, usado para recuperar datos de servidores. La biblioteca requests hace que las solicitudes GET sean increíblemente simples.

Solicitud GET básica

Así es como se hace una solicitud GET básica:

import requests
 
response = requests.get('https://api.github.com')
print(response.status_code)  # 200
print(response.text)  # Response body as string

Solicitud GET con parámetros de consulta (query)

En lugar de construir manualmente URLs con query strings, usa el 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 response

Solicitud GET con headers personalizados

Muchas APIs requieren headers personalizados para autenticación o negociación de contenido:

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())

Hacer solicitudes POST en Python

Las solicitudes POST envían datos a un servidor, comúnmente usadas para envíos de formularios y operaciones de API.

Solicitud POST con datos de formulario

Para enviar datos codificados como formulario (como envíos de formularios 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)

Solicitud POST con payload JSON

Las APIs REST modernas normalmente esperan payloads JSON. La biblioteca requests maneja la serialización JSON automáticamente:

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
)

Solicitud POST con archivos

Sube archivos usando el 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)

Otros métodos HTTP: PUT, PATCH, DELETE

La biblioteca requests soporta todos los métodos HTTP estándar:

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'))

Comprender el objeto Response

El objeto Response contiene toda la información sobre la respuesta del 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!")

Trabajar con headers de solicitud

Los headers llevan metadatos importantes sobre la solicitud:

Establecer 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)

Acceder a los headers de respuesta

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}")

Autenticación con Python Requests

La biblioteca requests soporta múltiples mecanismos de autenticación:

Autenticación básica (Basic)

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)

Autenticación con token Bearer

Común para tokens JWT y 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)

Autenticación con 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)

Autenticación OAuth 2.0

Para OAuth 2.0, usa la 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')

Sesiones para conexiones persistentes

Las sesiones mantienen cookies, pooling de conexiones y configuración a través de múltiples solicitudes:

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()

Sesión con autenticación

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')

Context manager para sesiones

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 block

Estrategias de timeout y reintento (retry)

Configura siempre timeouts para evitar que las solicitudes se queden colgadas indefinidamente:

Configurar 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)

Implementar lógica de reintentos (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')

Manejo de errores en Python Requests

Un manejo de errores robusto es crucial para aplicaciones en producción:

Manejar excepciones comunes

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")

Comprobar códigos de estado

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}")

Verificación SSL y certificados

Por defecto, requests verifica los 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')
)

Uso de proxies con Python Requests

Configura servidores proxy para las solicitudes:

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})

Comparación de bibliotecas HTTP en Python

Así es como la biblioteca requests se compara con alternativas:

Featurerequestsurllibhttpxaiohttp
Ease of UseExcellent (Pythonic API)Poor (verbose)ExcellentGood
Async SupportNoNoYesYes
HTTP/2 SupportNoNoYesNo
Session ManagementBuilt-inManualBuilt-inBuilt-in
JSON HandlingAutomaticManualAutomaticAutomatic
Connection PoolingYesNoYesYes
Standard LibraryNo (pip install)YesNo (pip install)No (pip install)
DocumentationExcellentGoodExcellentGood
PerformanceGoodFairExcellentExcellent (async)
SSL/TLSFull supportFull supportFull supportFull support
Best ForSynchronous HTTP, general useSimple scripts, no dependenciesModern sync/async HTTPHigh-performance async

Cuándo usar cada una:

  • requests: Opción por defecto para la mayoría de operaciones HTTP síncronas. Ideal para web scraping, consumo de APIs y tareas HTTP generales.
  • urllib: Solo cuando no puedes instalar paquetes externos (requisito de biblioteca estándar).
  • httpx: Cuando necesitas soporte HTTP/2 o quieres una API moderna compatible con requests con capacidades async.
  • aiohttp: Para aplicaciones asíncronas de alto rendimiento que manejan muchas solicitudes concurrentes.

Rate limiting y scraping responsable

Al hacer scraping de sitios web o llamar APIs, implementa 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}")

Respetar 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")

Ejemplos reales y casos de uso

Ejemplo 1: Consumir una 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")

Ejemplo 2: Descargar archivos con progreso

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')

Ejemplo 3: Web scraping con manejo de errores

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)}")

Ejemplo 4: Integración de API con paginación

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)}")

Probar APIs en Jupyter con RunCell

Al desarrollar y probar integraciones con APIs, RunCell (opens in a new tab) proporciona un entorno de agente impulsado por IA directamente en notebooks de Jupyter. En lugar de depurar manualmente solicitudes y respuestas HTTP, el agente inteligente de RunCell puede ayudarte a:

  • Construir y probar automáticamente solicitudes de API con la autenticación adecuada
  • Depurar el parseo de respuestas y el manejo de errores en tiempo real
  • Generar fragmentos de código para patrones HTTP comunes
  • Validar respuestas de API contra esquemas esperados
  • Iterar rápidamente sobre transformaciones de datos a partir de respuestas de API

Esto es especialmente valioso al trabajar con APIs complejas que requieren múltiples pasos de autenticación, manejo de paginación o lógica de parseo de datos intrincada. RunCell acelera el flujo de trabajo de desarrollo al reducir el ida y vuelta de probar solicitudes HTTP manualmente.

Preguntas frecuentes (FAQ)

¿Para qué se usa la biblioteca requests de Python?

La biblioteca requests de Python se utiliza para hacer solicitudes HTTP a servidores web y APIs. Simplifica tareas como obtener páginas web, consumir APIs REST, enviar datos de formularios, subir archivos y manejar autenticación. Es la biblioteca HTTP más popular en Python debido a su API intuitiva y su conjunto completo de funcionalidades.

¿Cómo instalo la biblioteca requests de Python?

Instala la biblioteca requests usando pip: pip install requests. Para entornos conda, usa conda install requests. Una vez instalada, impórtala con import requests en tu código Python. La biblioteca no forma parte de la biblioteca estándar de Python, por lo que se requiere instalación.

¿Cuál es la diferencia entre requests.get() y requests.post()?

requests.get() recupera datos de un servidor sin modificar nada, y normalmente se usa para obtener páginas web o datos de APIs. requests.post() envía datos al servidor para crear o actualizar recursos, comúnmente usado para envíos de formularios, carga de archivos u operaciones de API que modifican el estado del servidor. Las solicitudes GET pasan parámetros en la URL, mientras que las POST envían datos en el cuerpo de la solicitud.

¿Cómo manejo errores con la biblioteca requests de Python?

Usa bloques try-except para capturar excepciones de requests: ConnectionError para problemas de red, Timeout para respuestas lentas, HTTPError para códigos 4xx/5xx y RequestException como captura general. Llama a response.raise_for_status() después de cada solicitud para lanzar automáticamente HTTPError cuando la solicitud falle. Configura siempre timeouts para evitar que las solicitudes queden colgadas indefinidamente.

¿Cómo envío datos JSON con Python requests?

Usa el parámetro json en requests: requests.post(url, json=data). La biblioteca serializa automáticamente diccionarios de Python a JSON y establece el header Content-Type: application/json. Para parsear respuestas JSON, usa response.json(), que deserializa el cuerpo de la respuesta JSON en un diccionario de Python.

¿Debería usar requests o urllib en Python?

Usa la biblioteca requests para la mayoría de operaciones HTTP. Ofrece una API más limpia, manejo automático de JSON, gestión de sesiones integrada y mejor manejo de errores comparado con urllib. Usa urllib solo cuando no puedas instalar paquetes externos y debas depender exclusivamente de la biblioteca estándar de Python. Para aplicaciones modernas que requieren HTTP/2 o soporte async, considera httpx como alternativa.

¿Cómo agrego autenticación a Python requests?

Para autenticación Basic, usa requests.get(url, auth=('username', 'password')). Para tokens Bearer (JWT, OAuth), añade un header Authorization: headers = {'Authorization': f'Bearer {token}'}. Para API keys, agrégalas como parámetros de consulta usando el diccionario params o como headers personalizados como 'X-API-Key'. Las sesiones pueden mantener la autenticación entre múltiples solicitudes.

¿Qué son las sesiones en Python requests y cuándo debería usarlas?

Las sesiones mantienen configuración (headers, cookies, autenticación) a través de múltiples solicitudes al mismo servidor. Usa sesiones cuando hagas varias solicitudes a una API, cuando necesites mantener estado de inicio de sesión con cookies o cuando quieras reutilizar conexiones TCP para mejor rendimiento. Crea una sesión con session = requests.Session() y usa session.get() en lugar de requests.get().

Conclusión

La biblioteca requests de Python es una herramienta indispensable para la comunicación HTTP en Python. Su API elegante transforma operaciones HTTP complejas en código simple y legible. Desde solicitudes GET básicas hasta funciones avanzadas como autenticación, sesiones, carga de archivos y manejo de errores, requests proporciona todo lo que necesitas para interacciones HTTP robustas.

Al dominar los patrones y buenas prácticas de esta guía—configurar timeouts, implementar lógica de reintentos, manejar errores con elegancia y respetar límites de tasa—construirás aplicaciones confiables que se comunican eficazmente con servicios web y APIs. Ya sea que consumas APIs REST, hagas scraping de sitios web o construyas herramientas de automatización, la biblioteca requests hace que las operaciones HTTP sean directas y mantenibles.

📚