FastAPI is a modern Python web framework for building APIs. It's known for being fast, easy to use, and efficient. It uses standard Python type hints to validate data and automatically generate interactive documentation for your API. For more details on API design standards, see OpenAPI Specification.
This guide will walk you through everything you need to know to get started, from installation to building your first endpoints.
FastAPI is built on two main components:
This combination makes it simple to build APIs that are both fast and reliable.
async
and await
out of the box, allowing you to write non-blocking code that is great for I/O-heavy applications. For more on async programming in Python, see AsyncIO documentation.To get started, you need Python 3.8 or newer.
Install FastAPI:
Use pip
to install the FastAPI library. For more on Python packaging, see Python Packaging User Guide.
pip install fastapi
Install an ASGI Server: FastAPI needs an ASGI server to run. Uvicorn is the recommended choice.
pip install "uvicorn[standard]"
Let's create a basic API that returns a "Hello, FastAPI!" message.
Save this code in a file named main.py
:
from fastapi import FastAPI # Create a FastAPI application instance app = FastAPI() # Define a route for the root URL ("/") @app.get("/") def read_root(): return {"message": "Hello, FastAPI!"}
Explanation:
app = FastAPI()
creates your application.@app.get("/")
is a decorator that tells FastAPI that the function below it handles GET
requests for the root URL (/
).Now, run the application from your terminal:
uvicorn main:app --reload
The --reload
flag tells Uvicorn to automatically restart the server whenever you change your code. For more on running FastAPI in production, see FastAPI Deployment documentation.
Open your browser and go to http://127.0.0.1:8000
. You should see the following JSON response:
{"message": "Hello, FastAPI!"}
While a single main.py
file is great for getting started, real applications benefit from a more organized structure. A common approach is to separate different parts of your API into "routers."
Here is a simple project layout:
/myproject ├── app/ │ ├── __init__.py │ ├── main.py │ └── routers/ │ ├── __init__.py │ └── items.py └── requirements.txt
app/main.py
: This is where you create your main FastAPI
app instance and include routers from other files.app/routers/
: This directory holds different parts of your API. For example, items.py
would contain all routes related to items.This keeps your code clean and modular as your application grows. For more on organizing Python projects, see Python Application Layouts.
You can easily add parameters to your routes.
Path parameters are part of the URL path.
# In main.py @app.get("/items/{item_id}") def read_item(item_id: int): return {"item_id": item_id}
Here, {item_id}
is a path parameter. The type hint item_id: int
tells FastAPI to validate that the input is an integer. If you visit http://127.0.0.1:8000/items/5
, you'll get a valid response. If you visit http://127.0.0.1:8000/items/foo
, FastAPI will return an automatic validation error.
Query parameters are key-value pairs that come after the ?
in the URL.
# In main.py @app.get("/users/") def read_user(user_id: int, name: str | None = None): return {"user_id": user_id, "name": name}
Any function parameter that is not part of the path is automatically treated as a query parameter. Here, user_id
is required, while name
is optional.
You can call this endpoint like this: http://127.0.0.1:8000/users/?user_id=10&name=David
.
FastAPI automatically handles validation errors, but you'll often need to return custom errors from your application logic. You can do this using HTTPException
.
from fastapi import FastAPI, HTTPException app = FastAPI() items = {"foo": "The Foo Wrestlers"} @app.get("/items-db/{item_id}") def read_item_from_db(item_id: str): if item_id not in items: raise HTTPException(status_code=404, detail="Item not found") return {"item": items[item_id]}
If you try to access an item that doesn't exist (e.g., /items-db/bar
), you'll get a clean 404 Not Found
error with your custom message. For more on error handling, see FastAPI Error Handling documentation.
For POST
, PUT
, and PATCH
requests, you typically send data in the request body. FastAPI uses Pydantic models to define the structure of this data. You can also use these models to define the shape of your response and change the default status code.
from fastapi import FastAPI, status from pydantic import BaseModel class Item(BaseModel): name: str price: float is_offer: bool | None = None app = FastAPI() @app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED) def create_item(item: Item): # Here you would typically save the item to a database return item
Here, we've done three things:
Item
model for the request body.response_model=Item
to ensure the response conforms to the Item
schema. This is great for documentation and for filtering out extra data you don't want to return.status_code=status.HTTP_201_CREATED
to return a 201
status on successful creation, which is a standard REST API practice.If you'd like to see a full CRUD example with FastAPI and a database, check out my article: Connecting FastAPI to a Database with SQLModel.
One of FastAPI's best features is its automatic documentation. While your app is running, go to these URLs:
http://127.0.0.1:8000/docs
: This provides an interactive Swagger UI where you can see all your endpoints and test them directly.http://127.0.0.1:8000/redoc
: This provides alternative documentation using ReDoc.async/await
, it can take some time to get used to. For a primer, see AsyncIO documentation.This guide covers the basics. From here, you can explore more advanced topics to build production-ready applications:
FastAPI is a powerful and modern framework for building APIs in Python. Its focus on speed, developer experience, and automatic documentation makes it a great choice for projects of any size.
Q: Is FastAPI better than Flask or Django? A: It depends on your needs. FastAPI is faster and has built-in data validation and async support. Django is a "batteries-included" framework with an ORM and admin panel, making it good for larger, more traditional web applications. Flask is more minimalist and flexible.
Q: Do I have to use async
with FastAPI?
A: No. You can use regular def
functions for your routes, and FastAPI will run them in a thread pool. You only need async def
if you are performing non-blocking I/O operations. For more on async in Python, see AsyncIO documentation.
Q: What is an ASGI server? A: ASGI (Asynchronous Server Gateway Interface) is a standard interface between async-capable Python web servers, frameworks, and applications. Uvicorn and Hypercorn are popular ASGI servers.
Q: How do I connect FastAPI to a database? A: You can use any Python database library. SQLAlchemy is a popular choice for SQL databases, and you can integrate it using a dependency injection pattern.
Q: Where can I learn more? A: The official FastAPI documentation is an excellent and comprehensive resource.
David Muraya is a Solutions Architect specializing in Python, FastAPI, and Cloud Infrastructure. He is passionate about building scalable, production-ready applications and sharing his knowledge with the developer community. You can connect with him on LinkedIn.
Enjoyed this blog post? Check out these related posts!
Deploying Reflex Front-End with Caddy in Docker
A step-by-step guide to building and serving Reflex static front-end files using Caddy in a Docker container
Read More..
FastAPI Tutorial: A Complete Guide for Beginners
A step-by-step guide to building your first API with Python and FastAPI, from installation to production-ready concepts.
Read More..
How to Set Up a Custom Domain for Your Google Cloud Run service
A Step-by-Step Guide to Mapping Your Domain to Cloud Run
Read More..
Serving a React Frontend Application with FastAPI
A Guide to Serving Your Frontend and Backend from a Single Application
Read More..
Have a project in mind? Send me an email at hello@davidmuraya.com and let's bring your ideas to life. I am always available for exciting discussions.