Getting Started

Getting Started

Let’s write our first actix-web application!

Hello, world!

Start by creating a new binary-based Cargo project and changing into the new directory:

cargo new hello-world
cd hello-world

Now, add actix-web as a dependency of your project by ensuring your Cargo.toml contains the following:

actix-web = "2.0"

If you want to use the #[actix_rt::main] macro, you have to add actix-rt to your dependency. Now your Cargo.toml should look like following:

actix-web = "2.0"
actix-rt = "1.0"

In order to implement a web server, we first need to create a request handler.

A request handler is an async function that accepts zero or more parameters that can be extracted from a request (ie, impl FromRequest) and returns a type that can be converted into an HttpResponse (ie, impl Responder):

use actix_web::{web, App, HttpResponse, HttpServer, Responder};

async fn index() -> impl Responder {
    HttpResponse::Ok().body("Hello world!")

async fn index2() -> impl Responder {
    HttpResponse::Ok().body("Hello world again!")

Next, create an App instance and register the request handler with the application's route on a path and with a particular HTTP method. After that, the application instance can be used with HttpServer to listen for incoming connections. The server accepts a function that should return an application factory.

async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
            .route("/", web::get().to(index))
            .route("/again", web::get().to(index2))

That's it! Now, compile and run the program with cargo run. Head over to http://localhost:8088/ to see the results.

Note: You could notice #[actix_rt::main] attribute macro. This macro executes marked async function in actix runtime. Any async function could be marked and executed by this macro.

Using Attribute Macros to Define Routes

Alternatively, you can define routes using macro attributes which allow you to specify the routes above your functions like so:

use actix_web::get;

async fn index3() -> impl Responder {
    HttpResponse::Ok().body("Hey there!")

You can then register the route using service():


For consistency reasons, this documentation only uses the explicit syntax shown at the beginning of this page. However, if you prefer this syntax you should feel free to use it any time you declare a route as it's only syntactic sugar.

To learn more, see actix-web-codegen.


If you want, you can have an automatically reloading server during development that recompiles on demand. This isn't necessary, but it makes rapid prototyping more convenient as you can see changes instantly upon saving. To see how this can be accomplished, have a look at the autoreload pattern.

Next up: Application