Skip to content

05 Query Parameters

DodaTech 4 min read

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

  1. Missing required query parameters — Query parameters without defaults are required. Omitting them returns 422.
  2. 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.
  3. Forgetting to import Query — Query() provides validation and metadata. Import it from fastapi.
  4. Not using Optional for truly optional parameters — A parameter with default None should be typed as Optional[str] = None, not str = None.
  5. Overusing required query parameters — Most query parameters should be optional. Use defaults like page=1, limit=10 rather than requiring them.

Practice Questions

  1. How does FastAPI distinguish between path and query parameters?
  2. How do you make a query parameter required?
  3. What does Query(..., min_length=2) mean?
  4. How do you accept multiple values for the same query parameter?
  5. 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

Can query parameters have default values?

Yes, parameters with default values are optional. Parameters without defaults are required. FastAPI uses the Python default value syntax.

How do I handle boolean query parameters?

Use bool type hint. FastAPI accepts true, True, 1, and yes for True; false, False, 0, and no for False.

What is the difference between Optional[str] and str = None?

Optional[str] means the value can be str or None. str = None without Optional does the same thing but Optional is more explicit and preferred.

How do I validate query parameter values?

Use the Query() function with parameters like ge, le, min_length, max_length, and regex for string validation.

Can query parameters be lists?

Yes, use list[str] or List[str] from typing. Pass multiple values: ?tags=a&tags=b produces tags=['a', 'b'].

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