<p dir="auto">Opening a new issue since no action has been taken on <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="547604689" data-permission-text="Title is private" data-url="https://github.com/tiangolo/fastapi/issues/842" data-hovercard-type="issue" data-hovercard-url="/tiangolo/fastapi/issues/842/hovercard" href="https://github.com/tiangolo/fastapi/issues/842">#842</a> for more than a month.</p>
<p dir="auto">Looks like we have an issue on how fastapi handles lists of elements passed as <code class="notranslate">Form</code> parameter (so anything that is type hinted <code class="notranslate">List[...] = Form(...)</code>). The issue doesn't arise when they are defined as <code class="notranslate">Query</code> parameters.<br>
After some digging I managed to get to the root of the problem, which is <em>how</em> we pass the parameters when making an api call. fastapi indeed correctly understands that the input needs to be a list of elements, but doesn't parse the list if it comes from a single field.</p>
<p dir="auto">Example using <code class="notranslate">Query</code>, works as  expected</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@app.post(&quot;/&quot;)
def api_test(l: List[int] = Query(...)) -&gt; List[int]:
    return l"><pre class="notranslate"><span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">post</span>(<span class="pl-s">"/"</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">api_test</span>(<span class="pl-s1">l</span>: <span class="pl-v">List</span>[<span class="pl-s1">int</span>] <span class="pl-c1">=</span> <span class="pl-v">Query</span>(...)) <span class="pl-c1">-&gt;</span> <span class="pl-v">List</span>[<span class="pl-s1">int</span>]:
    <span class="pl-k">return</span> <span class="pl-s1">l</span></pre></div>
<p dir="auto">Api request generated using the swagger UI</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="curl -X 'GET' \
  'http://localhost:5009/?l=1&amp;l=2' \
  -H 'accept: application/json'"><pre class="notranslate">curl -X <span class="pl-s"><span class="pl-pds">'</span>GET<span class="pl-pds">'</span></span> \
  <span class="pl-s"><span class="pl-pds">'</span>http://localhost:5009/?l=1&amp;l=2<span class="pl-pds">'</span></span> \
  -H <span class="pl-s"><span class="pl-pds">'</span>accept: application/json<span class="pl-pds">'</span></span></pre></div>
<p dir="auto">note how the passed values are <code class="notranslate">l=1&amp;l=2</code></p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[
  1,
  2
]"><pre class="notranslate">[
  1,
  2
]</pre></div>
<p dir="auto">Example using <code class="notranslate">Form</code>, doesn't work as  expected</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@app.post(&quot;/&quot;)
def api_test(l: List[int] = Form(...)) -&gt; List[int]:
    return l"><pre class="notranslate"><span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">post</span>(<span class="pl-s">"/"</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">api_test</span>(<span class="pl-s1">l</span>: <span class="pl-v">List</span>[<span class="pl-s1">int</span>] <span class="pl-c1">=</span> <span class="pl-v">Form</span>(...)) <span class="pl-c1">-&gt;</span> <span class="pl-v">List</span>[<span class="pl-s1">int</span>]:
    <span class="pl-k">return</span> <span class="pl-s1">l</span></pre></div>
<p dir="auto">Api request generated using the swagger UI</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="curl -X 'POST' \
  'http://localhost:5009/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'l=1,2'"><pre class="notranslate">curl -X <span class="pl-s"><span class="pl-pds">'</span>POST<span class="pl-pds">'</span></span> \
  <span class="pl-s"><span class="pl-pds">'</span>http://localhost:5009/<span class="pl-pds">'</span></span> \
  -H <span class="pl-s"><span class="pl-pds">'</span>accept: application/json<span class="pl-pds">'</span></span> \
  -H <span class="pl-s"><span class="pl-pds">'</span>Content-Type: application/x-www-form-urlencoded<span class="pl-pds">'</span></span> \
  -d <span class="pl-s"><span class="pl-pds">'</span>l=1,2<span class="pl-pds">'</span></span></pre></div>
<p dir="auto">note how the passed values are <code class="notranslate">l=1,2</code></p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
  &quot;detail&quot;: [
    {
      &quot;loc&quot;: [
        &quot;body&quot;,
        &quot;l&quot;,
        0
      ],
      &quot;msg&quot;: &quot;value is not a valid integer&quot;,
      &quot;type&quot;: &quot;type_error.integer&quot;
    }
  ]
}"><pre class="notranslate">{
  <span class="pl-s"><span class="pl-pds">"</span>detail<span class="pl-pds">"</span></span>: [
    {
      <span class="pl-s"><span class="pl-pds">"</span>loc<span class="pl-pds">"</span></span>: [
        <span class="pl-s"><span class="pl-pds">"</span>body<span class="pl-pds">"</span></span>,
        <span class="pl-s"><span class="pl-pds">"</span>l<span class="pl-pds">"</span></span>,
        0
      ],
      <span class="pl-s"><span class="pl-pds">"</span>msg<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>value is not a valid integer<span class="pl-pds">"</span></span>,
      <span class="pl-s"><span class="pl-pds">"</span>type<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>type_error.integer<span class="pl-pds">"</span></span>
    }
  ]
}</pre></div>
<p dir="auto">Manual api request</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="curl -X 'POST' \
  'http://localhost:5009/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'l=1' \
  -d 'l=2'"><pre class="notranslate">curl -X <span class="pl-s"><span class="pl-pds">'</span>POST<span class="pl-pds">'</span></span> \
  <span class="pl-s"><span class="pl-pds">'</span>http://localhost:5009/<span class="pl-pds">'</span></span> \
  -H <span class="pl-s"><span class="pl-pds">'</span>accept: application/json<span class="pl-pds">'</span></span> \
  -H <span class="pl-s"><span class="pl-pds">'</span>Content-Type: application/x-www-form-urlencoded<span class="pl-pds">'</span></span> \
  -d <span class="pl-s"><span class="pl-pds">'</span>l=1<span class="pl-pds">'</span></span> \
  -d <span class="pl-s"><span class="pl-pds">'</span>l=2<span class="pl-pds">'</span></span></pre></div>
<p dir="auto">Now the values are passed as <code class="notranslate">-d 'l=1'</code> and <code class="notranslate">-d 'l=2'</code></p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[
  1,
  2
]"><pre class="notranslate">[
  1,
  2
]</pre></div>
<p dir="auto">I am fairly sure that <code class="notranslate">l=1,2</code> should be an accepted way of passing a list of values as parameter, but fastapi doesn't seem to like it. Also, if this isn't the case, the Swagger UI doesn't produce the correct curl requests for lists given as <code class="notranslate">Form</code> parameters.</p>
<p dir="auto">Packages:</p>
<ul dir="auto">
<li><code class="notranslate">fastapi</code>: <code class="notranslate">0.66.0</code></li>
<li><code class="notranslate">python</code>: <code class="notranslate">3.7.4</code></li>
</ul>
<p dir="auto">Let me know if you need other details!</p>
<p dir="auto">Thank you for coming to my TED talk</p>
<p dir="auto"><strong>Description</strong></p>
<p dir="auto">I need to support several query parameters with same name in GET route. Typical request looks like this:<br>
<a href="http://localhost/item?num=1&amp;num=2" rel="nofollow">http://localhost/item?num=1&amp;num=2</a></p>
<p dir="auto">I configured a route</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@app.get(&quot;/item&quot;, content_type=UJSONResponse)
async def get_part(num: list):
    found = False
    for i in num:
         if i in some_data:
             found = True
             break
    return {&quot;found&quot;: found}"><pre class="notranslate"><code class="notranslate">@app.get("/item", content_type=UJSONResponse)
async def get_part(num: list):
    found = False
    for i in num:
         if i in some_data:
             found = True
             break
    return {"found": found}
</code></pre></div>
<p dir="auto">The idea is, that I can pass several numbers to check, if they exist in some_data. In my opinion, it is not a good idea to get numbers from body here, because it is a simple GET request, but in current version application expects argument "num" in body, so on my request (written above) I receive a response</p>
<p dir="auto"><code class="notranslate">{"detail":[{"loc":["body","num"],"msg":"field required","type":"value_error.missing"}]}</code></p>
<p dir="auto">As I know, it is not restricted to pass several query parameters with the same name in an HTTP request by any specifications, so I would like to ask, is it possible to configure a route in FastAPI, which will be able to parse several query parameters with the same name?</p>