Annotated syntax for query parameter validation
Wrap the parameter type with `Annotated` to add validation metadata. For example, `q: Annotated[str | None] = None` is equivalent to `q: str | None = None` but allows adding validation rules inside `Annotated`. The actual default value remains in the function parameter, not in the `Query` object.
Query max_length validation
Use `Query(max_length=50)` inside `Annotated` to enforce that a query parameter string does not exceed a maximum character length. For example: `q: Annotated[str | None, Query(max_length=50)] = None`. FastAPI will validate the data, show clear errors for invalid data, and document the parameter in the OpenAPI schema.
Query min_length validation
Use `Query(min_length=3)` inside `Annotated` to enforce a minimum character length for a query parameter. For example: `q: Annotated[str | None, Query(min_length=3)] = None`.
Query pattern validation with regular expressions
Use `Query(pattern="...")` to define a regular expression pattern that a query parameter must match. For example: `q: Annotated[str, Query(pattern="^fixedquery$")] = Query()` ensures the parameter exactly matches the string 'fixedquery'. The pattern `^` marks the start and `$` marks the end of the string.
Old style Query as default value
Before FastAPI 0.95.0, `Query` was used as the default value of the function parameter instead of inside `Annotated`. Example: `q: str | None = Query(default=None, max_length=50)`. This style is deprecated but still supported. The `Annotated` approach is now preferred.
Cannot use Query default parameter inside Annotated
When using `Query` inside `Annotated`, do not use the `default` parameter in `Query`. Instead, use the actual default value of the function parameter. For example, use `q: Annotated[str, Query()] = "rick"` not `q: Annotated[str, Query(default="rick")] = "morty"` because it would be unclear which default value applies.
Advantages of Annotated over old Query default style
Using `Annotated` is better than using `Query` as the default value because: the actual default value of the function parameter is truly the default (more intuitive with Python), the function can be called in other places without FastAPI and will work as expected, the editor will complain about missing required parameters, and the same function can be used with other tools like Typer.
Required query parameter with Annotated
To make a query parameter required when using `Annotated` with `Query`, do not declare a default value in the function parameter. Example: `q: Annotated[str, Query(min_length=3)]` (no `= ...` part) makes the parameter required.
Required parameter that accepts None
To declare a query parameter that can accept `None` but is still required (forcing clients to send a value even if it is `None`), declare `None` as a valid type without a default value. Example: `q: Annotated[str | None, Query()]` with no default value makes it required, but clients can send `None`.
Query parameter list with multiple values
To declare a query parameter that can receive multiple values, use `list` in the type annotation with `Query`. Example: `q: Annotated[list[str], Query()]` allows the parameter to appear multiple times in the URL like `?q=foo&q=bar`. A URL like `http://localhost:8000/items/?q=foo&q=bar` would return `{"q": ["foo", "bar"]}`.
Query parameter list must use Query explicitly
When declaring a query parameter as a list type to accept multiple values, you must explicitly use `Query`. Otherwise, FastAPI will interpret it as a request body instead of a query parameter.
Query parameter list with default values
You can define a default list of values for a query parameter that accepts multiple values. Example: `q: Annotated[list[str], Query()] = ["foo", "bar"]` sets a default list. If the URL is `http://localhost:8000/items/` without query parameters, the response will be `{"q": ["foo", "bar"]}`.
Query parameter using plain list type
You can use `list` directly instead of `list[str]` in a query parameter type annotation. Example: `q: Annotated[list, Query()]`. However, FastAPI will not validate or document the contents of the list. Use `list[int]` or `list[str]` to enable validation of list contents.
Query parameter title metadata
Use the `title` parameter in `Query` to add a human-readable title for the parameter. Example: `q: Annotated[str | None, Query(title="Query string")] = None`. The title appears in the generated OpenAPI schema and documentation.
Query parameter description metadata
Use the `description` parameter in `Query` to add a description for the parameter. Example: `q: Annotated[str | None, Query(description="Query string for searching items")] = None`. The description appears in the generated OpenAPI schema and documentation interfaces.
Query parameter alias
Use the `alias` parameter in `Query` to accept a query parameter with a name that is not a valid Python variable name. Example: `item_query: Annotated[str, Query(alias="item-query")]` allows the URL parameter to be `item-query` (with hyphen) while the Python variable is `item_query` (with underscore). The client sends `?item-query=value` in the URL.
Query parameter deprecated flag
Use the `deprecated=True` parameter in `Query` to mark a query parameter as deprecated in the documentation. Example: `q: Annotated[str | None, Query(deprecated=True)] = None`. The OpenAPI documentation will clearly show the parameter as deprecated.
Exclude query parameter from OpenAPI schema
Use the `include_in_schema=False` parameter in `Query` to exclude a query parameter from the generated OpenAPI schema and automatic documentation. Example: `q: Annotated[str | None, Query(include_in_schema=False)] = None`.
Custom validation with Pydantic AfterValidator
Use Pydantic's `AfterValidator` inside `Annotated` to apply custom validation logic to a query parameter after normal validation. Example: `q: Annotated[str, AfterValidator(custom_validator_function)]` where the function receives the validated value and returns it or raises an error. This requires Pydantic version 2 or above.
Custom validation use cases
Custom validators in `AfterValidator` should only be used for validation that requires checking only the same data provided in the request. For validation that requires communicating with external components like a database or another API, use FastAPI Dependencies instead.
Query parameter validation summary
Generic validations and metadata for query parameters: `alias`, `title`, `description`, `deprecated`. String-specific validations: `min_length`, `max_length`, `pattern`. Custom validations use `AfterValidator`. All are applied through `Query` inside `Annotated` or as the default value.
Python types supported for automatic parameter validation
FastAPI supports automatic validation for parameters with Python type annotations including: `str`, `int`, `float`, `bool`, `list`, `dict`, union types like `str | None`, and custom types with Pydantic models. The validation is performed automatically based on the type annotation provided.
status_code parameter in path operation decorator
You can declare the HTTP status code used for the response by passing the status_code parameter to the path operation decorator (@app.get(), @app.post(), @app.put(), @app.delete(), etc). The status_code parameter receives a number with the HTTP status code and is a parameter of the decorator method, not of the path operation function.
status_code accepts IntEnum values
The status_code parameter can receive an IntEnum, such as Python's http.HTTPStatus, in addition to numeric values.
HTTP status code ranges and meanings
HTTP status codes are three-digit numeric codes sent in responses. The ranges are: 100-199 for Information responses (rarely used directly, cannot have a body); 200-299 for Successful responses (200 is default, 201 is Created, 204 is No Content with no body); 300-399 for Redirection (may or may not have a body, except 304 Not Modified which must not); 400-499 for Client errors (404 is Not Found, 400 is generic); 500-599 for Server errors (almost never used directly, returned automatically on application errors).
fastapi.status convenience module
FastAPI provides fastapi.status module with convenience variables for HTTP status codes, allowing you to use editor autocomplete to find them instead of memorizing numeric codes. These are the same variables as starlette.status, provided as a developer convenience.
status_code effect on response and documentation
When you specify a status_code parameter, FastAPI will return that status code in the response and document it in the OpenAPI schema and user interface documentation.
Response codes without body automatically documented
FastAPI knows which HTTP response codes indicate that the response should not have a body (such as 204 No Content). When these codes are used, FastAPI automatically produces OpenAPI documentation stating there is no response body.
Server-Sent Events (SSE) added in FastAPI 0.135.0
Server-Sent Events (SSE) support was added to FastAPI in version 0.135.0.
SSE format and field structure
SSE is a standard for streaming data from server to client over HTTP. Each event is a small text block with fields like data, event, id, and retry, separated by blank lines.
Stream SSE with yield and EventSourceResponse
To stream SSE with FastAPI, use yield in the path operation function and set response_class=EventSourceResponse. Import EventSourceResponse from fastapi.sse.
SSE return type AsyncIterable for validation and serialization
Declare the return type as AsyncIterable[Item] so FastAPI will validate, document, and serialize the data using Pydantic. This provides higher performance because Pydantic serializes on the Rust side.
SSE with non-async functions uses Iterable return type
For regular def functions (without async) that yield SSE data, the correct return type would be Iterable[Item]. FastAPI ensures it runs correctly without blocking the event loop.
SSE without explicit return type uses jsonable_encoder
You can omit the return type annotation for SSE endpoints. FastAPI will use jsonable_encoder to convert the data and send it.
ServerSentEvent object for custom SSE fields
To set SSE fields like event, id, retry, or comment, yield ServerSentEvent objects instead of plain data. Import ServerSentEvent from fastapi.sse.
SSE data field is always JSON encoded
The data field in ServerSentEvent is always encoded as JSON. You can pass any value that can be serialized as JSON, including Pydantic models.
SSE raw_data for non-JSON encoded content
Use raw_data instead of data in ServerSentEvent to send data without JSON encoding. This is useful for sending pre-formatted text, log lines, or special sentinel values like [DONE].
SSE data and raw_data are mutually exclusive
You can only set either data or raw_data on each ServerSentEvent, not both.
SSE resumption with Last-Event-ID header
When a browser reconnects after a connection drop, it sends the last received id in the Last-Event-ID header. You can read this as a header parameter to resume the stream from where the client left off.
SSE works with any HTTP method including POST
SSE works with any HTTP method, not just GET. This is useful for protocols like MCP that stream SSE over POST.
FastAPI SSE automatic keep-alive ping comment
FastAPI sends a keep-alive ping comment every 15 seconds when there hasn't been any message to prevent some proxies from closing the connection, as suggested in the HTML specification: Server-Sent Events.
FastAPI SSE Cache-Control header prevents caching
FastAPI automatically sets the Cache-Control: no-cache header on SSE responses to prevent caching of the stream.
FastAPI SSE X-Accel-Buffering header prevents proxy buffering
FastAPI automatically sets the X-Accel-Buffering: no header on SSE responses to prevent buffering in some proxies like Nginx.