[{"data":1,"prerenderedAt":103},["ShallowReactive",2],{"qa-\u002Ffastapi\u002Frouting\u002Fpath-query-params":3},{"page":4,"siblings":90,"blog":81},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":80,"related":81,"seo":82,"seoDescription":83,"stem":84,"subtopic":85,"topic":86,"topicSlug":87,"updated":88,"__hash__":89},"qa\u002Ffastapi\u002Frouting\u002Fpath-query-params.md","Path Query Params",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"easy","md","FastAPI","fastapi",{},true,1,"\u002Ffastapi\u002Frouting\u002Fpath-query-params",[23,27,31,35,39,44,48,52,56,60,64,68,72,76],{"id":24,"difficulty":14,"q":25,"a":26},"path-param-basics","How do you define and read a path parameter in FastAPI?","Declare the parameter name inside curly braces in the path string and add a\nmatching argument to the handler function. FastAPI parses and type-coerces it\nautomatically.\n\n```python\n@app.get(\"\u002Fitems\u002F{item_id}\")\nasync def get_item(item_id: int):\n    return {\"item_id\": item_id}\n# GET \u002Fitems\u002F42 → {\"item_id\": 42} (integer, not string)\n```\n\nIf the value can't be coerced to the declared type, FastAPI returns 422.\n\nRule of thumb: always type-annotate path parameters so FastAPI validates the URL\nsegment before the handler runs.\n",{"id":28,"difficulty":14,"q":29,"a":30},"query-param-basics","How do you define a required query parameter in FastAPI?","Declare a function parameter with a type annotation and **no default value**.\nFastAPI treats any simple type not in the path template as a query parameter.\n\n```python\n@app.get(\"\u002Fitems\")\nasync def search_items(q: str):\n    return {\"q\": q}\n# GET \u002Fitems?q=laptop → {\"q\": \"laptop\"}\n# GET \u002Fitems        → 422 (required param missing)\n```\n\nRule of thumb: no default → required query param; add `= None` or `= value`\nto make it optional.\n",{"id":32,"difficulty":14,"q":33,"a":34},"query-param-default","How do you give a query parameter a default value?","Assign a default in the function signature. FastAPI uses it when the client\nomits the parameter.\n\n```python\n@app.get(\"\u002Fitems\")\nasync def list_items(\n    page: int = 1,\n    size: int = 20,\n    active: bool = True,\n):\n    return {\"page\": page, \"size\": size, \"active\": active}\n# GET \u002Fitems → {\"page\": 1, \"size\": 20, \"active\": true}\n# GET \u002Fitems?page=3 → {\"page\": 3, \"size\": 20, \"active\": true}\n```\n\nRule of thumb: choose defaults that represent the most common use case so\nclients don't need to pass boilerplate on every request.\n",{"id":36,"difficulty":14,"q":37,"a":38},"bool-query-param","How does FastAPI parse boolean query parameters?","FastAPI accepts a flexible range of truthy\u002Ffalsy string values and converts them\nto Python `bool`:\n\n- Truthy: `\"1\"`, `\"true\"`, `\"on\"`, `\"yes\"` (case-insensitive)\n- Falsy: `\"0\"`, `\"false\"`, `\"off\"`, `\"no\"` (case-insensitive)\n\n```python\n@app.get(\"\u002Fitems\")\nasync def list_items(active: bool = True):\n    ...\n# GET \u002Fitems?active=false → active = False\n# GET \u002Fitems?active=0    → active = False\n# GET \u002Fitems?active=yes  → active = True\n```\n\nAny other value triggers a 422 validation error.\n\nRule of thumb: use `bool` for feature flags\u002Ffilters in query params — FastAPI's\nflexible string-to-bool coercion covers all common client conventions.\n",{"id":40,"difficulty":41,"q":42,"a":43},"path-query-same-name","medium","What happens if a path parameter and a query parameter have the same name?","FastAPI gives priority to the **path parameter**. A parameter name that appears\nin the route template `\u002F{name}` is always a path parameter; you cannot also read\nit from the query string with the same name in the same handler.\n\n```python\n@app.get(\"\u002Fitems\u002F{id}\")\nasync def get_item(id: int, q: str | None = None):\n    # id → from path, q → from query\n    ...\n```\n\nIf you genuinely need both a path and query parameter with the same name, use an\nalias: `Query(alias=\"id\")` — though this is a design smell.\n\nRule of thumb: keep path and query parameter names distinct; collision means\nyou should rethink the route design.\n",{"id":45,"difficulty":41,"q":46,"a":47},"path-helper","What is `Path()` and when should you use it instead of a bare type annotation?","`Path()` is FastAPI's parameter helper for adding **metadata and validation\nconstraints** to path parameters while keeping the type annotation clean.\n\n```python\nfrom typing import Annotated\nfrom fastapi import Path\n\n@app.get(\"\u002Fitems\u002F{item_id}\")\nasync def get_item(\n    item_id: Annotated[int, Path(title=\"Item ID\", ge=1, le=999_999)],\n):\n    return {\"id\": item_id}\n```\n\nConstraints (`ge`, `le`, `gt`, `lt`) are enforced at validation time and\nreflected in the OpenAPI schema. You can also pass `description`, `example`, and\n`deprecated`.\n\nRule of thumb: use `Path()` whenever a path parameter has a meaningful range,\ndescription, or example worth documenting in the schema.\n",{"id":49,"difficulty":41,"q":50,"a":51},"query-helper","What extra control does `Query()` give you over a plain query parameter annotation?","`Query()` adds string constraints (`min_length`, `max_length`, `pattern`),\nnumeric bounds, metadata (`title`, `description`, `example`), and the ability\nto collect multi-value parameters.\n\n```python\nfrom typing import Annotated\nfrom fastapi import Query\n\n@app.get(\"\u002Fsearch\")\nasync def search(\n    q: Annotated[str, Query(\n        min_length=3,\n        max_length=100,\n        description=\"Search term\",\n        example=\"fastapi\",\n    )],\n    sort: Annotated[str, Query(pattern=r\"^(asc|desc)$\")] = \"asc\",\n):\n    ...\n```\n\nRule of thumb: add `Query()` the moment you need any constraint or documentation\non a query parameter — it's zero runtime cost and improves the schema immediately.\n",{"id":53,"difficulty":41,"q":54,"a":55},"multi-value-query","How do you accept a list of values for the same query parameter key?","Annotate with `list[T]` and wrap with `Query()`:\n\n```python\nfrom typing import Annotated\nfrom fastapi import Query\n\n@app.get(\"\u002Fitems\")\nasync def filter_items(\n    tags: Annotated[list[str], Query()] = [],\n):\n    return {\"tags\": tags}\n# GET \u002Fitems?tags=python&tags=web → {\"tags\": [\"python\", \"web\"]}\n```\n\nWithout `Query()`, `list[str]` would be interpreted as a JSON body parameter.\nAn empty list default (`= []`) means the param is optional; use `= Query(min_length=1)`\non the list if at least one tag is required.\n\nRule of thumb: `list[T]` + `Query()` = multi-value param; the client repeats\nthe key multiple times in the query string.\n",{"id":57,"difficulty":41,"q":58,"a":59},"alias-parameter","How do you use a different query string key than the Python parameter name?","Pass `alias=` to `Query()` or `Path()`. FastAPI reads the value from the alias\nkey in the request but binds it to the Python name in the handler.\n\n```python\nfrom typing import Annotated\nfrom fastapi import Query\n\n@app.get(\"\u002Fitems\")\nasync def list_items(\n    item_query: Annotated[str | None, Query(alias=\"item-query\")] = None,\n):\n    return {\"query\": item_query}\n# GET \u002Fitems?item-query=foo → item_query = \"foo\"\n```\n\nThis is useful when the URL convention requires hyphens (which are invalid\nPython identifiers) or when you're preserving backward-compatible parameter names.\n\nRule of thumb: use `alias` to bridge the gap between URL naming conventions\n(hyphens) and Python naming conventions (underscores).\n",{"id":61,"difficulty":14,"q":62,"a":63},"deprecated-param","How do you mark a query parameter as deprecated in the OpenAPI schema?","Pass `deprecated=True` to `Query()` or `Path()`. The parameter still works\nat runtime — it's marked deprecated in the generated schema only.\n\n```python\nfrom typing import Annotated\nfrom fastapi import Query\n\n@app.get(\"\u002Fitems\")\nasync def list_items(\n    q: Annotated[str | None, Query()] = None,\n    search: Annotated[str | None, Query(deprecated=True)] = None,  # old alias\n):\n    effective_q = q or search\n    ...\n```\n\nSwagger UI renders deprecated parameters with a strikethrough and a warning badge.\n\nRule of thumb: mark old parameter names deprecated rather than removing them\nimmediately — gives clients a migration window while keeping the schema honest.\n",{"id":65,"difficulty":41,"q":66,"a":67},"numeric-constraints","What numeric constraints can you apply to path and query parameters in FastAPI?","| Constraint | Meaning |\n|------------|---------|\n| `ge=n` | greater than or equal (`>=`) |\n| `gt=n` | strictly greater than (`>`) |\n| `le=n` | less than or equal (`\u003C=`) |\n| `lt=n` | strictly less than (`\u003C`) |\n| `multiple_of=n` | value must be a multiple of n |\n\n```python\nfrom typing import Annotated\nfrom fastapi import Query, Path\n\n@app.get(\"\u002Fitems\u002F{item_id}\")\nasync def get_item(\n    item_id: Annotated[int, Path(ge=1)],           # ID must be positive\n    page: Annotated[int, Query(ge=1, le=100)] = 1, # page 1-100\n    price_min: Annotated[float, Query(gt=0)] = 0.0,\n):\n    ...\n```\n\nConstraints are reflected in the OpenAPI JSON Schema properties so client\nvalidators can enforce them before the request is sent.\n\nRule of thumb: apply `ge=1` to all ID path parameters — negative or zero IDs\nare almost always bugs.\n",{"id":69,"difficulty":41,"q":70,"a":71},"string-constraints","What string constraints are available for query parameters?","| Constraint | Meaning |\n|------------|---------|\n| `min_length=n` | minimum string length |\n| `max_length=n` | maximum string length |\n| `pattern=r\"...\"` | regex the value must match |\n\n```python\nfrom typing import Annotated\nfrom fastapi import Query\n\n@app.get(\"\u002Fusers\")\nasync def search_users(\n    username: Annotated[str, Query(min_length=3, max_length=50, pattern=r\"^\\w+$\")],\n):\n    ...\n# GET \u002Fusers?username=al → 422 (min_length=3)\n# GET \u002Fusers?username=al!ce → 422 (pattern)\n```\n\nRule of thumb: always set `max_length` on free-text query params to prevent\naccidental DoS from clients sending huge query strings.\n",{"id":73,"difficulty":14,"q":74,"a":75},"exclude-from-schema","How do you hide a query parameter from the OpenAPI schema?","Pass `include_in_schema=False` to `Query()`. The parameter still works at runtime\nbut won't appear in `\u002Fopenapi.json` or the docs.\n\n```python\nfrom typing import Annotated\nfrom fastapi import Query\n\n@app.get(\"\u002Fitems\")\nasync def list_items(\n    q: str | None = None,\n    _internal_trace_id: Annotated[str | None, Query(include_in_schema=False)] = None,\n):\n    ...\n```\n\nRule of thumb: use `include_in_schema=False` for internal\u002Finfra params\n(tracing IDs, A\u002FB test flags) that aren't part of the public API contract.\n",{"id":77,"difficulty":41,"q":78,"a":79},"path-vs-query-design","When should a resource identifier be a path parameter vs a query parameter?","**Path parameters** are for identifying a specific resource:\n```python\nGET \u002Fusers\u002F{user_id}       # identifies a specific user\nGET \u002Forders\u002F{order_id}\u002Fitems  # items within a specific order\n```\n\n**Query parameters** are for filtering, sorting, searching or pagination of a collection:\n```python\nGET \u002Fusers?role=admin&page=2   # filter users by role, paginate\nGET \u002Forders?status=pending     # filter orders\n```\n\nMixing them up leads to ugly URLs like `\u002Fusers?id=42` (should be `\u002Fusers\u002F42`)\nor `\u002Fusers\u002Fadmin` for a filter (should be `\u002Fusers?role=admin`).\n\nRule of thumb: if removing the identifier would leave a meaningless URL\n(`\u002Fusers\u002F` is just a list), it belongs in the path; if it's a filter, it's a query param.\n",14,null,{"description":11},"FastAPI path and query parameter interview questions — type coercion, optional params, validation constraints, multi-value query params and Path\u002FQuery helpers.","fastapi\u002Frouting\u002Fpath-query-params","Path & Query Parameters","Routing & Parameters","routing","2026-06-20","X4UtReULzyfYdlFbaM_Q6J6VrwdK5UfMWRcLWh4kW0I",[91,92,95,99],{"subtopic":85,"path":21,"order":20},{"subtopic":93,"path":94,"order":12},"Request Body","\u002Ffastapi\u002Frouting\u002Frequest-body",{"subtopic":96,"path":97,"order":98},"Response Models","\u002Ffastapi\u002Frouting\u002Fresponse-models",3,{"subtopic":100,"path":101,"order":102},"Routers & Structure","\u002Ffastapi\u002Frouting\u002Frouters",4,1782244112667]