FastAPI is a modern, high-performance web framework for building APIs with Python 3.6+ based on standard Python type hints. It’s known for its simplicity, speed, and automatic documentation support. However, one of the most common issues developers face when using FastAPI—especially for the first time—is the mysterious:
HTTP 422 Unprocessable Entity error
This error often pops up when you’re sending JSON data in a POST request, but FastAPI doesn’t know how to handle it.
In this blog post, we’ll go over:
- What causes the 422 error in FastAPI
- How to properly send JSON data
- How to define the correct request body in FastAPI
- Full working example
- References for further learning
The Problem: 422 Error When Sending JSON
Let’s say you have this basic FastAPI code:
from fastapi import FastAPI
app = FastAPI()
@app.post("/")
def main(user):
return user
You try sending a POST request using Python’s requests
library or JavaScript (Axios):
Python Request
import requests
response = requests.post("http://127.0.0.1:8000", json={"user": "smith"})
print(response.text)
JavaScript (Axios)
axios.post("http://127.0.0.1:8000", { user: "smith" })
.then(res => console.log(res.data));
Expected: The API should echo back the user.
Actual: You get:
{
"detail": [
{
"loc": ["query", "user"],
"msg": "field required",
"type": "value_error.missing"
}
]
}
Or simply a 422 Unprocessable Entity error.
##The Reason: FastAPI Expects Request Body, Not Query Parameters
In FastAPI, unless you explicitly tell it otherwise, it assumes basic parameters like user
are query parameters — not body content.
So in the code above:
@app.post("/")
def main(user):
return user
FastAPI thinks you’re expecting /?user=smith
in the URL — not JSON data in the request body.
That’s why your JSON { "user": "smith" }
is rejected, resulting in the 422 error.
The Fix: Use a Pydantic Model for JSON Body
To properly accept JSON data in a POST request, you need to define a Pydantic model that describes the expected body content.
Updated FastAPI Code:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserInput(BaseModel):
user: str
@app.post("/")
def main(user_input: UserInput):
return user_input
Why this works:
- FastAPI now knows to look in the request body for JSON that matches the
UserInput
schema. - It parses the input automatically, validates it, and returns 422 only if the input doesn’t match the schema.
Sample Request:
POST / HTTP/1.1
Content-Type: application/json
{
"user": "smith"
}
This will now work correctly.
##Full Working Example
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserInput(BaseModel):
user: str
@app.post("/")
def main(user_input: UserInput):
return {"received_user": user_input.user}
Test it with:
curl -X POST http://127.0.0.1:8000/ \
-H "Content-Type: application/json" \
-d '{"user": "smith"}'
Or using Python:
import requests
response = requests.post("http://127.0.0.1:8000", json={"user": "smith"})
print(response.json())
Response:
{
"received_user": "smith"
}
Bonus: Case Sensitivity and Type Hints
- FastAPI relies heavily on Python type hints.
- Always use proper capitalization and matching types in your models.
- Use tools like Swagger UI (built-in at
/docs
) to test your APIs.
Conclusion
If you’re getting a 422 Unprocessable Entity error in FastAPI when sending JSON data via a POST request, the fix is simple:
Use a Pydantic model to define what your API expects in the request body.
FastAPI does the rest — parsing, validation, and error handling.