How do you type-hint repeated query params in FastAPI?

Tests FastAPI's Annotated pattern for multi-value query strings. A great answer uses Annotated[list[str], Query()] = [] to collect repeated keys, and notes the old Query-as-default alternative. Red flag: manual parsing or typing it as str.
WHAT THIS TESTS: This question checks your command of FastAPI's modern dependency injection and type declaration system, specifically how it handles multiple values for a single query key. The interviewer is looking for knowledge of the Annotated syntax, awareness of how FastAPI coerces repeated URL parameters into Python collections, and the ability to distinguish between single-value and multi-value query parameters. It also reveals whether you keep up with current FastAPI conventions or rely on outdated patterns.
A GOOD ANSWER COVERS: First, import Annotated from typing and Query from fastapi. Second, declare the parameter as keyword: Annotated[list[str], Query()] = [] so FastAPI automatically aggregates every occurrence of the keyword key into a single Python list. Third, explain the concrete behavior: a request to /search?keyword=python&keyword=fastapi results in the function receiving ["python", "fastapi"]. Fourth, acknowledge the older alternative where Query was used as a default value, like keyword: list[str] = Query(default=[]), but emphasize that Annotated is now preferred because it separates validation metadata from the default value and avoids mutable default pitfalls.
COMMON WRONG ANSWERS: Using str as the type hint, which only captures the last occurrence and silently drops earlier values. Suggesting manual inspection of Request.query_params, which bypasses FastAPI's automatic validation, serialization, and OpenAPI generation. Declaring list[str] without Query or Annotated, which may function but prevents you from adding constraints such as min_length or max_length on individual items. Using a mutable default like = [] directly in the function signature without Annotated, which is a well-known Python anti-pattern even though FastAPI handles it safely in many cases.
LIKELY FOLLOW-UPS: How would you enforce that at least one keyword must be provided, or set a maximum of five keywords? The answer is to keep Annotated[list[str], Query(min_length=1, max_length=5)] or similar validation arguments. Another follow-up is what happens if the parameter appears only once; FastAPI still wraps the single value in a list because the type hint declares list[str]. They might also ask how to provide default values inside Query versus in the assignment, which tests your understanding of Annotated scoping.
ONE CONCRETE EXAMPLE: from typing import Annotated from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/search") async def search(keyword: Annotated[list[str], Query()] = []): return {"results_for": keyword}
When a client calls /search?keyword=python&keyword=fastapi, the endpoint receives keyword as ["python", "fastapi"]. If the client omits the parameter entirely, keyword defaults to an empty list.
Source: fastapi.tiangolo.com
Read the original → fastapi.tiangolo.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.