Skip to main content

Query Parameters

Query parameters are the key-value pairs that appear after the ? in a URL, typically used for filtering, sorting, and pagination. In this codebase, query parameters are managed through the Query class and its base class Param, both located in fastapi/params.py.

Core Parameter Classes

The implementation of query parameters relies on a hierarchy that integrates with Pydantic's validation system:

  • Param: The base class for all request parameters (Query, Path, Header, Cookie). It inherits from Pydantic's FieldInfo and adds an in_ attribute to specify the parameter's location in the request.
  • Query: A specialized version of Param where in_ is set to ParamTypes.query. It provides the interface for defining metadata and validation rules specific to URL query strings.
# fastapi/params.py

class Param(FieldInfo):
in_: ParamTypes
# ... handles common logic for aliases, validation, and metadata

class Query(Param):
in_ = ParamTypes.query
# ... inherits all validation and metadata capabilities

Defining Query Parameters

FastAPI automatically interprets function parameters that are not part of the path as query parameters. You can define them using simple type hints or by using the Query class for more control.

Implicit Query Parameters

If you provide a type hint but no default value or Query instance, the parameter is treated as a required query parameter. If you provide a default value, it becomes optional.

@app.get("/items/")
async def read_items(q: str | None = None, skip: int = 0, limit: int = 10):
return {"q": q, "skip": skip, "limit": limit}

Explicit Definition with Query

The Query class allows you to add validation and metadata. The modern and recommended approach in this codebase is to use Annotated.

from typing import Annotated
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(max_length=50, min_length=3)] = None
):
return {"q": q}

Validation and Constraints

The Query class supports a wide range of validation constraints inherited from Param and Pydantic's FieldInfo.

String Validations

You can constrain strings using length limits and regular expression patterns (using the pattern parameter).

@app.get("/items/")
async def read_items(
q: Annotated[
str | None,
Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None
):
return {"q": q}

Note: The regex parameter is deprecated in favor of pattern in fastapi/params.py.

Numeric Validations

For integer or float parameters, you can use:

  • gt: Greater than
  • ge: Greater than or equal
  • lt: Less than
  • le: Less than or equal
@app.get("/items/")
async def read_items(
limit: Annotated[int, Query(gt=0, le=100)] = 10
):
return {"limit": limit}

Required vs. Optional Parameters

A query parameter's requirement is determined by its default value:

  1. Optional: Provide a default value (e.g., None or 10).
  2. Required: Do not provide a default value, or explicitly use ... (Ellipsis) or Undefined.
from fastapi import Query
from fastapi._compat import Undefined

@app.get("/items/")
async def read_items(
q: str = Query(default=...), # Required
p: str = Query(default=Undefined) # Also Required
):
return {"q": q, "p": p}

Advanced Configuration

Aliases

Query parameters often need to use characters that are not valid Python variable names, such as hyphens. The alias parameter allows you to map a URL parameter name to a different function argument name.

@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(alias="item-query")] = None
):
# Client sends ?item-query=foo, but code uses 'q'
return {"q": q}

Multiple Values (Lists)

To accept multiple values for the same query parameter (e.g., ?q=foo&q=bar), define the type hint as a list.

@app.get("/items/")
async def read_items(q: Annotated[list[str] | None, Query()] = None):
return {"q": q}

Grouping with Pydantic Models

For complex sets of query parameters, you can group them into a Pydantic model. This promotes reusability and cleaner function signatures.

from pydantic import BaseModel, Field

class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"

@app.get("/items/")
async def read_items(filter_query: FilterParams = Query()):
return filter_query

OpenAPI Metadata

The Query class includes several parameters that do not affect validation but are used to generate the OpenAPI schema and documentation:

  • title: A human-readable name for the parameter.
  • description: A detailed explanation of what the parameter does.
  • examples: A list of example values to show in the documentation.
  • deprecated: Marks the parameter as deprecated in the schema.
  • include_in_schema: Set to False to hide the parameter from the generated OpenAPI documentation.
@app.get("/items/")
async def read_items(
q: Annotated[
str | None,
Query(
title="Query string",
description="Query string for the items to search in the database",
examples=["foo", "bar"],
deprecated=True
),
] = None
):
return {"q": q}