Query Parameters
Query parameters are the key=value pairs after the ? in a URL. In FastAPI, any function parameter that is not a path parameter automatically becomes a query parameter - its type hint controls validation, and a default value makes it optional.
Basic Query Parameters
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
def read_items(skip: int = 0, limit: int = 100):
return {"skip": skip, "limit": limit}
GET /items/?skip=5&limit=10 returns {"skip": 5, "limit": 10}. Without parameters the defaults are used. The docs at /docs show both parameters with their types and defaults.
Optional Query Parameters
Declare a parameter as str | None (or with a default of None) to make it explicitly optional:
@app.get("/search/")
def search(q: str | None = None):
if q:
return {"query": q}
return {"query": None}
Constrained Query Parameters
from typing import Annotated
from pydantic import Field
@app.get("/items/")
def read_items(
skip: Annotated[int, Field(ge=0)] = 0,
limit: Annotated[int, Field(ge=1, le=100)] = 10,
):
return {"skip": skip, "limit": limit}
Violations produce a 422 with the exact constraint that failed - no manual if-checks needed.
Lists, Enums and Booleans
from enum import Enum
class Category(str, Enum):
books = "books"
toys = "toys"
@app.get("/items/")
def read_items(categories: list[Category] | None = None, verbose: bool = False):
return {"categories": categories, "verbose": verbose}
Repeat the parameter (?categories=books&categories=toys) for list values; booleans accept true/1/yes.
Summary
Non-path parameters become query parameters automatically. Use type hints for conversion, defaults for optionality, Annotated + Field for constraints, and list/enum types for repeated or enumerated values. The generated docs always reflect the current signature.