05 Query Parameters
title: Query Parameters in FastAPI REST APIs weight: 15 date: 2026-06-28 lastmod: 2026-06-28 description: Master FastAPI query parameters with type hints, defaults, validation, optional parameters, and automatic documentation for filtering, sorting, and pagination. tags: [api-development, fastapi]
FastAPI query parameters are extracted from URL query strings automatically based on function parameter names that are not path parameters, with type hints, default values, validation, and automatic OpenAPI documentation.
```mermaid
flowchart TD
A[Query Parameters] --> B[Function Parameters]
B --> C[Not in path]
B --> D[Have defaults]
A --> E[Types]
E --> F[str, int, bool]
E --> G[Optional types]
E --> H[Lists]
A --> I[Validation]
I --> J[Query() with constraints]
style A fill:#e1f5fe
style B fill:#fff9c4
style E fill:#c8e6c9
Any function parameter that is not declared as a path parameter becomes a query parameter. Parameters with default values are optional. Parameters without defaults are required. FastAPI validates types and generates documentation automatically.
Think of query parameters like filter options on a shopping website. The page number (page=2), items per page (limit=20), and search term (q=laptop) are query parameters that refine what you see.
Example: Basic Query Parameters
from fastapi import FastAPI
from typing import Optional
app = FastAPI()
items = [
{"id": 1, "name": "Laptop", "category": "electronics", "price": 999},
{"id": 2, "name": "Shirt", "category": "clothing", "price": 29},
{"id": 3, "name": "Phone", "category": "electronics", "price": 699},
]
@app.get("/api/items")
def list_items(
category: Optional[str] = None,
min_price: Optional[float] = None,
max_price: Optional[float] = None,
sort_by: str = "name",
order: str = "asc"
):
"""Filter items with optional query parameters."""
result = items.copy()
if category:
result = [i for i in result if i["category"] == category]
if min_price is not None:
result = [i for i in result if i["price"] >= min_price]
if max_price is not None:
result = [i for i in result if i["price"] <= max_price]
reverse = order == "desc"
result.sort(key=lambda x: x.get(sort_by, ""), reverse=reverse)
return {"count": len(result), "data": result}
# GET /api/items?category=electronics&min_price=500&sort_by=price&order=desc
Expected output:
{"count":2,"data":[{"id":3,"name":"Phone","category":"electronics","price":699},{"id":1,"name":"Laptop","category":"electronics","price":999}]}
Example: Query Parameter Validation
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/api/products")
def search_products(
q: str = Query(None, min_length=2, max_length=100, description="Search query"),
page: int = Query(1, ge=1, description="Page number"),
limit: int = Query(10, ge=1, le=100, description="Items per page"),
in_stock: bool = Query(True, description="Only show in-stock items"),
tags: list[str] = Query([], description="Filter by tags")
):
return {
"query": q,
"pagination": {"page": page, "limit": limit},
"filters": {"in_stock": in_stock, "tags": tags}
}
# GET /api/products?q=laptop&page=2&limit=20&in_stock=true&tags=electronics&tags=sale
Expected output:
{"query":"laptop","pagination":{"page":2,"limit":20},"filters":{"in_stock":true,"tags":["electronics","sale"]}}
Example: Required vs Optional Query Parameters
from fastapi import FastAPI, Query
from typing import Optional
from datetime import date
app = FastAPI()
@app.get("/api/orders")
def list_orders(
# Required query parameter
user_id: int = Query(..., description="User ID is required"),
# Optional with defaults
status: Optional[str] = Query(None, regex="^(pending|completed|cancelled)$"),
start_date: Optional[date] = None,
end_date: Optional[date] = None,
page: int = 1,
limit: int = Query(10, le=50)
):
return {
"user_id": user_id,
"filters": {
"status": status,
"date_range": {"start": str(start_date), "end": str(end_date)}
},
"pagination": {"page": page, "limit": limit}
}
# Valid: GET /api/orders?user_id=42&status=pending&start_date=2026-01-01
# Invalid: GET /api/orders (missing required user_id)
Common Mistakes
- Missing required query parameters — Query parameters without defaults are required. Omitting them returns 422.
- Using the wrong type for query parameters — Query parameters come as strings. If you declare Optional[int], FastAPI converts to int. Float strings like "not-a-number" trigger validation errors.
- Forgetting to import Query — Query() provides validation and metadata. Import it from fastapi.
- Not using Optional for truly optional parameters — A parameter with default None should be typed as Optional[str] = None, not str = None.
- Overusing required query parameters — Most query parameters should be optional. Use defaults like page=1, limit=10 rather than requiring them.
Practice Questions
- How does FastAPI distinguish between path and query parameters?
- How do you make a query parameter required?
- What does Query(..., min_length=2) mean?
- How do you accept multiple values for the same query parameter?
- Challenge: Create a products search endpoint with query parameters for text search (q), category, price range (min_price, max_price), rating (min_rating), sorting (sort_by, order), pagination (page, limit), and availability (in_stock). Add validation for all parameters.
FAQ
Mini Project
Build an API for a movie database with extensive query parameter support. Include: text search (q), genre filter (multiple), year range (year_gte, year_lte), rating filter (min_rating), sort options (sort_by: title/year/rating, order: asc/desc), and pagination (page, limit). Add validation for all parameters.
What's Next
Now learn about Pydantic request bodies in Building REST APIs with FastAPI.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro