Skip to main content

Request Parameters and Headers

FastAPI provides a set of tools to define and validate data from different parts of the request: path parameters, query parameters, headers, and cookies. These are implemented using classes in fastapi.params that inherit from Pydantic's FieldInfo, allowing you to leverage Pydantic's validation rules while automatically generating OpenAPI documentation.

Parameter Types and Locations

FastAPI uses the Param class in fastapi.params.py as a base for all non-body request parameters. The specific location of a parameter is defined by the ParamTypes enum (and the corresponding ParameterInType in fastapi.openapi.models):

  • Path: Parameters extracted from the URL path (e.g., /items/{item_id}).
  • Query: Parameters extracted from the URL query string (e.g., ?q=search).
  • Header: Parameters extracted from HTTP headers.
  • Cookie: Parameters extracted from request cookies.

Path Parameters

Path parameters are defined in the path of your operation decorator. Because they are part of the URL structure, they are always required and cannot have a default value. FastAPI enforces this in the Path class constructor in fastapi/params.py:

class Path(Param):
def __init__(self, default: Any = ..., **kwargs):
assert default is ..., "Path parameters cannot have a default value"
super().__init__(default=default, **kwargs)

In your application, you use Path to add metadata or validation:

from typing import Annotated
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(
item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)]
):
return {"item_id": item_id}

Query Parameters

Query parameters are the default for any function parameters that are scalar types (like str, int, bool) and are not found in the path. You can use the Query class to add explicit validation:

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, pattern="^fixedquery$")] = None
):
return {"q": q}

Header Parameters and Automatic Conversion

HTTP headers are often case-insensitive and use hyphens (e.g., User-Agent), but Python variable names cannot contain hyphens. By default, the Header class in fastapi.params converts underscores to hyphens.

This behavior is controlled by the convert_underscores parameter in the Header constructor:

# fastapi/params.py
class Header(Param):
def __init__(self, ..., convert_underscores: bool = True, **kwargs):
self.convert_underscores = convert_underscores
super().__init__(..., **kwargs)

When FastAPI processes the request in fastapi/dependencies/utils.py, it performs this conversion:

# fastapi/dependencies/utils.py
if not field_info.alias and getattr(field_info, "convert_underscores", None):
alias = param_name.replace("_", "-")

This allows you to define a parameter as user_agent and have FastAPI automatically look for the User-Agent header:

from typing import Annotated
from fastapi import FastAPI, Header

app = FastAPI()

@app.get("/items/")
async def read_items(user_agent: Annotated[str | None, Header()] = None):
return {"User-Agent": user_agent}

Grouping Parameters with Pydantic Models

For endpoints with many parameters, you can group them into a single Pydantic model. FastAPI will extract the fields from the model based on the parameter function you use (e.g., Header(), Query()).

from typing import Annotated
from fastapi import FastAPI, Header
from pydantic import BaseModel

app = FastAPI()

class CommonHeaders(BaseModel):
host: str
save_data: bool
if_modified_since: str | None = None
x_tag: list[str] = []

@app.get("/items/")
async def read_items(headers: Annotated[CommonHeaders, Header()]):
return headers

Internally, fastapi/dependencies/utils.py uses _get_flat_fields_from_params to expand these models into individual fields for validation and documentation.

OpenAPI Documentation and Examples

FastAPI maps your parameter definitions to the OpenAPI Parameter model defined in fastapi/openapi/models.py. This model includes fields like name, in, description, required, and deprecated.

Multiple Examples

You can provide multiple examples for a parameter using the openapi_examples argument. This is distinct from the JSON Schema examples field.

from fastapi import FastAPI, Header
from fastapi.openapi.models import Example

app = FastAPI()

@app.get("/header_examples/")
def header_examples(
data: str | None = Header(
default=None,
openapi_examples={
"Example One": {
"summary": "A simple example",
"value": "header1",
},
"Example Two": {
"summary": "Another example",
"value": "header2",
},
},
),
):
return data

FastAPI's OpenAPI utility (fastapi/openapi/utils.py) processes these examples when generating the final schema:

# fastapi/openapi/utils.py
openapi_examples = getattr(field_info, "openapi_examples", None)
if openapi_examples:
parameter["examples"] = jsonable_encoder(openapi_examples)

Deprecation

To mark a parameter as deprecated in the OpenAPI UI, pass deprecated=True to the parameter function. This sets the deprecated field in the underlying Parameter model:

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

Security Parameters

For security schemes like API keys, FastAPI provides specialized classes in fastapi.security that use the APIKeyIn enum from fastapi.openapi.models. This enum defines valid locations for API keys: query, header, or cookie.

# fastapi/openapi/models.py
class APIKeyIn(Enum):
query = "query"
header = "header"
cookie = "cookie"

When you use APIKeyHeader(name="x-api-key"), FastAPI creates an internal APIKey model that specifies the location, ensuring the security scheme is correctly documented in the OpenAPI components/securitySchemes section.