starlette

Lightweight ASGI framework and toolkit — the foundation underlying FastAPI. starlette features: Router for URL routing, Request/Response primitives, WebSocket support, BackgroundTasks for fire-and-forget, StaticFiles for serving assets, TestClient (synchronous httpx wrapper for testing async apps), Middleware (SessionMiddleware, CORSMiddleware, GZipMiddleware, HTTPSRedirectMiddleware), mount for sub-applications, StreamingResponse for generator-based responses, FileResponse for file downloads, and JSONResponse/HTMLResponse/PlainTextResponse helpers. Used directly when FastAPI overhead is unwanted.

Evaluated Mar 06, 2026 (0d ago) v0.36.x
Homepage ↗ Repo ↗ Developer Tools python starlette ASGI async middleware routing websocket fastapi
⚙ Agent Friendliness
69
/ 100
Can an agent use this?
🔒 Security
90
/ 100
Is it safe for agents?
⚡ Reliability
87
/ 100
Does it work consistently?

Score Breakdown

⚙ Agent Friendliness

MCP Quality
--
Documentation
90
Error Messages
85
Auth Simplicity
99
Rate Limits
99

🔒 Security

TLS Enforcement
92
Auth Strength
88
Scope Granularity
88
Dep. Hygiene
92
Secret Handling
90

ASGI framework with no built-in auth. HTTPSRedirectMiddleware enforces HTTPS. TrustedHostMiddleware prevents host header injection. SessionMiddleware uses signed cookies — keep SECRET_KEY secret. CORSMiddleware: configure allow_origins specifically, avoid wildcard in production. StaticFiles: disable directory listing for production.

⚡ Reliability

Uptime/SLA
88
Version Stability
88
Breaking Changes
85
Error Recovery
88
AF Security Reliability

Best When

Building custom ASGI frameworks, middleware, or lightweight services where FastAPI's overhead is unwanted — starlette is the foundation of FastAPI and provides all ASGI primitives directly.

Avoid When

Full REST API with automatic validation (use FastAPI), traditional WSGI apps (use Flask), or when you need full-stack framework features (use Django).

Use Cases

  • Agent ASGI app — from starlette.applications import Starlette; from starlette.routing import Route; from starlette.responses import JSONResponse; async def homepage(request): return JSONResponse({'status': 'ok'}); app = Starlette(routes=[Route('/', homepage)]) — minimal ASGI; agent creates lightweight ASGI app without FastAPI overhead; run with uvicorn app:app
  • Agent background tasks — from starlette.background import BackgroundTasks; async def send_email(request): tasks = BackgroundTasks(); tasks.add_task(send_notification, email=request.query_params['email']); return JSONResponse({'status': 'queued'}, background=tasks) — fire-and-forget; agent runs tasks after response sent; background= parameter on response triggers after response delivered
  • Agent middleware stack — from starlette.middleware import Middleware; from starlette.middleware.cors import CORSMiddleware; app = Starlette(middleware=[Middleware(CORSMiddleware, allow_origins=['*'], allow_methods=['*'])]) — CORS; agent adds middleware to ASGI app; middleware list applies in order; starlette middlewares work with any ASGI framework
  • Agent WebSocket endpoint — from starlette.websockets import WebSocket; async def ws_endpoint(websocket: WebSocket): await websocket.accept(); data = await websocket.receive_text(); await websocket.send_text(f'Echo: {data}'); await websocket.close() — WebSocket; agent handles WebSocket connections with accept/receive/send/close lifecycle
  • Agent streaming response — from starlette.responses import StreamingResponse; async def stream(request): async def generator(): for chunk in data: yield chunk; return StreamingResponse(generator(), media_type='text/plain') — streaming; agent streams large responses without loading into memory; generator yields bytes or strings; media_type controls Content-Type

Not For

  • Full-featured REST APIs — starlette lacks FastAPI's automatic validation, OpenAPI, and dependency injection; use FastAPI for API development
  • Django-style batteries — no ORM, admin interface, or auth system; starlette is a toolkit not a full framework
  • WSGI apps — starlette is ASGI-only; for WSGI use Flask/Django

Interface

REST API
No
GraphQL
No
gRPC
No
MCP Server
No
SDK
Yes
Webhooks
No

Authentication

Methods: none
OAuth: No Scopes: No

No built-in auth — ASGI toolkit. Implement auth via middleware or use authlib/python-jose.

Pricing

Model: open_source
Free tier: Yes
Requires CC: No

starlette is BSD 3-Clause licensed. Created by Tom Christie (encode). Free for all use.

Agent Metadata

Pagination
none
Idempotent
Full
Retry Guidance
Not documented

Known Gotchas

  • Request body can only be read once — await request.body() consumes the stream; calling request.body() twice raises error; agent code needing body in middleware AND endpoint: cache body on request.state or read in middleware and pass forward; request.json() also consumes; use starlette's Request.body() pattern with caching
  • Route ordering matters — Starlette matches routes in order; Route('/items/{id}') before Route('/items/special') means 'special' is never reached; agent code: put specific routes before parameterized routes; or use Mount for sub-application isolation
  • WebSocket lifecycle: accept before receive — await websocket.accept() must be called before receive/send; skipping accept raises RuntimeError; agent code: always accept() first; WebSocketDisconnect raised on client disconnect — catch it: try: while True: msg = await websocket.receive_text() except WebSocketDisconnect: handle_disconnect()
  • BackgroundTask exceptions are silently swallowed — tasks.add_task(fn) runs fn after response; if fn raises exception it's logged but not re-raised; agent code: wrap background tasks with try/except and explicit error logging; response returns 200 even if background task fails
  • Middleware order is reversed from declaration — app = Starlette(middleware=[MiddlewareA, MiddlewareB]); MiddlewareB wraps first (inner), MiddlewareA wraps outer; request passes A→B→endpoint; response passes endpoint→B→A; agent code: put authentication middleware first in list (outermost wrapper)
  • TestClient requires app as argument not URL — from starlette.testclient import TestClient; client = TestClient(app) — not TestClient('http://localhost'); TestClient runs app in-process via ASGI transport; agent test code: no server needed; client.get('/path') dispatches directly to app

Alternatives

Full Evaluation Report

Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for starlette.

$99

Scores are editorial opinions as of 2026-03-06.

5208
Packages Evaluated
26151
Need Evaluation
173
Need Re-evaluation
Community Powered