CORS en FastAPI

Básico
FastAPI
FastAPI
Actualizado: 18/04/2026

Diagrama: Fastapi cors

¿Qué es CORS?

CORS (Cross-Origin Resource Sharing) es un mecanismo de seguridad implementado en los navegadores web que controla qué sitios web pueden realizar peticiones HTTP a un dominio diferente al suyo. Cuando tu frontend en https://mi-app.com intenta llamar a tu API en https://api.mi-empresa.com, el navegador comprueba si la API permite este acceso antes de realizar la petición real.

Esta política de seguridad se llama Same-Origin Policy y es una protección fundamental del navegador. Sin embargo, en el desarrollo moderno, es muy habitual que el frontend y el backend vivan en dominios o puertos distintos.

¿Cuándo aparece el error de CORS?

El error de CORS aparece en el navegador cuando:

  • Tu frontend en http://localhost:3000 llama a tu API en http://localhost:8000
  • Tu app de React/Vue/Angular en https://miapp.com llama a una API en https://api.miapp.com
  • Un cliente externo intenta acceder a tu API desde un dominio no autorizado

El mensaje de error en la consola del navegador suele ser:

Access to fetch at 'http://localhost:8000/api/datos' from origin
'http://localhost:3000' has been blocked by CORS policy.

Las peticiones preflight

Antes de enviar ciertos tipos de peticiones (POST, PUT, DELETE, o peticiones con cabeceras personalizadas), el navegador envía una petición preflight OPTIONS para preguntar a la API si permite ese tipo de petición. La API debe responder con los headers CORS adecuados.

CORSMiddleware en FastAPI

FastAPI incluye CORSMiddleware de Starlette para gestionar CORS de forma declarativa. Se añade con app.add_middleware():

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/api/datos")
async def obtener_datos():
    return {"datos": "accesibles desde el frontend"}

Parámetros principales de CORSMiddleware

| Parámetro | Tipo | Descripción | |---|---|---| | allow_origins | list[str] | Lista de orígenes permitidos | | allow_origin_regex | str | Patrón regex para orígenes permitidos | | allow_methods | list[str] | Métodos HTTP permitidos | | allow_headers | list[str] | Cabeceras HTTP permitidas | | allow_credentials | bool | Permite cookies y cabeceras Authorization | | expose_headers | list[str] | Cabeceras visibles para el navegador | | max_age | int | Segundos que el navegador cachea el preflight |

Configuración para desarrollo

Durante el desarrollo local, es habitual que el frontend corra en un puerto distinto al backend:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# Orígenes típicos en desarrollo local
origenes_desarrollo = [
    "http://localhost:3000",   # React por defecto
    "http://localhost:4200",   # Angular por defecto
    "http://localhost:5173",   # Vite por defecto
    "http://127.0.0.1:3000",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origenes_desarrollo,
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
    allow_headers=["Authorization", "Content-Type", "X-Requested-With"],
)

Configuración con comodín para desarrollo rápido

Si quieres permitir cualquier origen durante el desarrollo (útil para pruebas rápidas):

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Permitir cualquier origen
    allow_methods=["*"],  # Permitir cualquier método HTTP
    allow_headers=["*"],  # Permitir cualquier cabecera
)

Importante: El comodín "*" no puede combinarse con allow_credentials=True. Si necesitas credenciales, debes especificar los orígenes explícitamente.

Configuración para producción

En producción, la configuración debe ser más restrictiva para garantizar la seguridad:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic_settings import BaseSettings

class Configuracion(BaseSettings):
    allowed_origins: list[str] = ["https://miapp.com"]
    debug: bool = False

    class Config:
        env_file = ".env"

config = Configuracion()
app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=config.allowed_origins,
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
    max_age=3600,  # El navegador cachea el preflight 1 hora
)

En el archivo .env de producción:

ALLOWED_ORIGINS=["https://miapp.com","https://www.miapp.com"]

CORS con credenciales (cookies y Authorization)

Cuando tu frontend envía cookies o la cabecera Authorization en sus peticiones, necesitas habilitar allow_credentials=True:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    # Con credentials, los orígenes DEBEN ser explícitos (no "*")
    allow_origins=[
        "https://miapp.com",
        "https://admin.miapp.com",
    ],
    allow_credentials=True,  # Permite enviar cookies y Authorization
    allow_methods=["*"],
    allow_headers=["*"],
)

Y en el frontend (JavaScript/TypeScript), debes incluir credentials: "include" en las peticiones:

const respuesta = await fetch("https://api.miapp.com/usuarios", {
    method: "GET",
    credentials: "include",  // Envía las cookies con la petición
    headers: {
        "Authorization": `Bearer ${token}`
    }
});

CORS con regex para subdominios

Si tienes múltiples subdominios que deben acceder a tu API, puedes usar una expresión regular:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    # Permite cualquier subdominio de miapp.com
    allow_origin_regex=r"https://.*\.miapp\.com",
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Esto permitirá peticiones desde https://app.miapp.com, https://admin.miapp.com, https://tienda.miapp.com, etc.

Configuración dinámica según el entorno

Un patrón habitual es diferenciar la configuración CORS según el entorno de ejecución:

import os
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

ENTORNO = os.getenv("ENTORNO", "desarrollo")

if ENTORNO == "produccion":
    origenes = [
        "https://miapp.com",
        "https://www.miapp.com",
    ]
    allow_all = False
elif ENTORNO == "staging":
    origenes = [
        "https://staging.miapp.com",
        "https://preview.miapp.com",
    ]
    allow_all = False
else:
    # Desarrollo: orígenes locales
    origenes = [
        "http://localhost:3000",
        "http://localhost:5173",
        "http://127.0.0.1:3000",
    ]
    allow_all = True

app.add_middleware(
    CORSMiddleware,
    allow_origins=origenes,
    allow_credentials=not allow_all,
    allow_methods=["*"],
    allow_headers=["*"],
)

Verificar que CORS funciona correctamente

Para comprobar que CORS está configurado correctamente, puedes usar curl para simular una petición preflight:

curl -v \
  -X OPTIONS \
  -H "Origin: http://localhost:3000" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: Content-Type, Authorization" \
  http://localhost:8000/api/endpoint

La respuesta debe incluir las cabeceras:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, PUT, ...
Access-Control-Allow-Headers: Content-Type, Authorization

Si estas cabeceras aparecen en la respuesta, CORS está configurado correctamente y el navegador permitirá la petición.

Fuentes y referencias

Documentación oficial y recursos externos para profundizar en FastAPI

Documentación oficial de FastAPI
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, FastAPI es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de FastAPI

Explora más contenido relacionado con FastAPI y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Comprender qué es CORS y por qué los navegadores bloquean peticiones entre dominios. Configurar CORSMiddleware en FastAPI para permitir orígenes específicos. Usar comodines y configuraciones dinámicas de CORS para distintos entornos. Habilitar credenciales CORS para peticiones con cookies y cabeceras de autorización. Configurar CORS correctamente para entornos de desarrollo y producción.