> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/tokio-rs/axum/llms.txt
> Use this file to discover all available pages before exploring further.

# Extractors

> Extract data from HTTP requests using Axum's powerful extractor system

Extractors allow you to pull data from HTTP requests in a type-safe way. They implement either the `FromRequestParts` or `FromRequest` trait.

## How extractors work

Extractors are types that implement `FromRequest` or `FromRequestParts`. When used as handler arguments, Axum automatically extracts the data:

```rust theme={null}
use axum::{
    extract::{Path, Query},
    http::HeaderMap,
};
use serde::Deserialize;

#[derive(Deserialize)]
struct Params {
    page: u32,
}

async fn handler(
    Path(id): Path<u32>,
    Query(params): Query<Params>,
    headers: HeaderMap,
) -> String {
    format!("ID: {}, Page: {}", id, params.page)
}
```

## Common extractors

Axum provides many built-in extractors:

<Tabs>
  <Tab title="Path">
    Extract data from the URL path:

    ```rust theme={null}
    use axum::{Router, routing::get, extract::Path};
    use serde::Deserialize;

    // Single parameter
    async fn get_user(Path(id): Path<u32>) -> String {
        format!("User ID: {}", id)
    }

    // Multiple parameters as tuple
    async fn get_team(
        Path((user_id, team_id)): Path<(u32, u32)>
    ) -> String {
        format!("User {} in team {}", user_id, team_id)
    }

    // Multiple parameters as struct
    #[derive(Deserialize)]
    struct TeamParams {
        user_id: u32,
        team_id: u32,
    }

    async fn get_team_struct(
        Path(TeamParams { user_id, team_id }): Path<TeamParams>
    ) -> String {
        format!("User {} in team {}", user_id, team_id)
    }

    let app = Router::new()
        .route("/users/:id", get(get_user))
        .route("/users/:user_id/team/:team_id", get(get_team));
    ```
  </Tab>

  <Tab title="Query">
    Extract query parameters:

    ```rust theme={null}
    use axum::{Router, routing::get, extract::Query};
    use serde::Deserialize;

    #[derive(Deserialize)]
    struct Pagination {
        page: Option<u32>,
        per_page: Option<u32>,
    }

    async fn list_items(
        Query(pagination): Query<Pagination>
    ) -> String {
        let page = pagination.page.unwrap_or(1);
        let per_page = pagination.per_page.unwrap_or(10);
        format!("Page {}, {} items per page", page, per_page)
    }

    let app = Router::new()
        .route("/items", get(list_items));
    // Handles: GET /items?page=2&per_page=20
    ```
  </Tab>

  <Tab title="Json">
    Parse JSON request bodies:

    ```rust theme={null}
    use axum::{Router, routing::post, Json};
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize)]
    struct CreateUser {
        name: String,
        email: String,
    }

    #[derive(Serialize)]
    struct User {
        id: u64,
        name: String,
        email: String,
    }

    async fn create_user(
        Json(payload): Json<CreateUser>
    ) -> Json<User> {
        Json(User {
            id: 1,
            name: payload.name,
            email: payload.email,
        })
    }

    let app = Router::new()
        .route("/users", post(create_user));
    ```
  </Tab>

  <Tab title="Form">
    Parse URL-encoded form data:

    ```rust theme={null}
    use axum::{Router, routing::post, Form};
    use serde::Deserialize;

    #[derive(Deserialize, Debug)]
    struct Input {
        name: String,
        email: String,
    }

    async fn accept_form(
        Form(input): Form<Input>
    ) -> String {
        format!("Name: {}, Email: {}", input.name, input.email)
    }

    let app = Router::new()
        .route("/subscribe", post(accept_form));
    ```
  </Tab>

  <Tab title="Headers">
    Access request headers:

    ```rust theme={null}
    use axum::{
        Router,
        routing::get,
        http::{HeaderMap, StatusCode},
    };

    async fn handler(
        headers: HeaderMap
    ) -> Result<String, StatusCode> {
        if let Some(user_agent) = headers.get("user-agent") {
            Ok(format!("User-Agent: {:?}", user_agent))
        } else {
            Err(StatusCode::BAD_REQUEST)
        }
    }

    let app = Router::new()
        .route("/", get(handler));
    ```
  </Tab>

  <Tab title="State">
    Access shared application state:

    ```rust theme={null}
    use axum::{
        Router,
        routing::get,
        extract::State,
    };

    #[derive(Clone)]
    struct AppState {
        counter: u32,
    }

    async fn handler(
        State(state): State<AppState>
    ) -> String {
        format!("Counter: {}", state.counter)
    }

    let state = AppState { counter: 0 };

    let app = Router::new()
        .route("/", get(handler))
        .with_state(state);
    ```

    See [State](/concepts/state) for more details.
  </Tab>
</Tabs>

## The order of extractors

<Warning>
  The order of extractors in your handler signature matters!
</Warning>

Extractors are processed in order:

1. **`FromRequestParts` extractors** come first (Path, Query, State, headers, etc.)
2. **`FromRequest` extractors** come last (body extractors like Json, Form, Bytes)

```rust theme={null}
use axum::{
    extract::{Path, Query, State},
    Json,
    http::HeaderMap,
};

#[derive(Clone)]
struct AppState {}

// ✅ Correct order
async fn correct(
    State(state): State<AppState>,     // FromRequestParts
    Path(id): Path<u32>,                // FromRequestParts
    Query(params): Query<Params>,       // FromRequestParts
    headers: HeaderMap,                  // FromRequestParts
    Json(payload): Json<CreateUser>,    // FromRequest (body)
) {}

// ❌ Wrong - body extractor before Path
async fn wrong(
    Json(payload): Json<CreateUser>,    // FromRequest - too early!
    Path(id): Path<u32>,                // Won't compile
) {}
```

## Optional extractors

Use `Option<T>` to make an extractor optional:

```rust theme={null}
use axum::{
    extract::{Path, Query},
    Router,
    routing::get,
};

async fn handler(
    path: Option<Path<String>>,
    query: Option<Query<Params>>,
) -> String {
    match (path, query) {
        (Some(Path(p)), Some(Query(q))) => 
            format!("Path: {}, Query: {:?}", p, q),
        _ => "Missing data".to_string(),
    }
}
```

## The `Request` extractor

Extract the entire request:

```rust theme={null}
use axum::{
    extract::Request,
    http::Method,
};

async fn handler(request: Request) -> String {
    format!("Method: {}, URI: {}", request.method(), request.uri())
}
```

<Note>
  `Request` is a `FromRequest` extractor, so it must come last (or second-to-last if using `Next` in middleware).
</Note>

## FromRequest vs FromRequestParts

Understanding the difference:

<Accordion title="FromRequestParts">
  Extractors that only need access to the request head (method, URI, headers, extensions):

  * `Path`
  * `Query`
  * `State`
  * `HeaderMap`
  * `Method`
  * `Uri`

  Multiple `FromRequestParts` extractors can be used in any order.
</Accordion>

<Accordion title="FromRequest">
  Extractors that consume the request body:

  * `Json`
  * `Form`
  * `Bytes`
  * `String`
  * `Request`

  Only one `FromRequest` extractor can be used per handler, and it must come last (except for `Next` in middleware).
</Accordion>

## Custom extractors

Create your own extractors by implementing `FromRequestParts` or `FromRequest`:

```rust theme={null}
use axum::{
    async_trait,
    extract::FromRequestParts,
    http::{request::Parts, StatusCode},
};

struct ApiToken(String);

#[async_trait]
impl<S> FromRequestParts<S> for ApiToken
where
    S: Send + Sync,
{
    type Rejection = StatusCode;

    async fn from_request_parts(
        parts: &mut Parts,
        _state: &S
    ) -> Result<Self, Self::Rejection> {
        if let Some(auth) = parts.headers.get("authorization") {
            if let Ok(value) = auth.to_str() {
                return Ok(ApiToken(value.to_string()));
            }
        }
        Err(StatusCode::UNAUTHORIZED)
    }
}

// Use in handlers
async fn protected(token: ApiToken) -> String {
    format!("Token: {}", token.0)
}
```

## Derive macros

<Tip>
  Use the `FromRequest` derive macro to create custom extractors more easily:

  ```rust theme={null}
  use axum::{
      extract::{FromRequest, rejection::JsonRejection},
      http::StatusCode,
      response::{IntoResponse, Response},
  };

  // Custom JSON extractor with better error messages
  #[derive(FromRequest)]
  #[from_request(via(axum::Json), rejection(AppError))]
  struct AppJson<T>(T);

  struct AppError(JsonRejection);

  impl IntoResponse for AppError {
      fn into_response(self) -> Response {
          (StatusCode::BAD_REQUEST, "Invalid JSON").into_response()
      }
  }
  ```
</Tip>

## Next steps

<CardGroup cols={2}>
  <Card title="State" icon="database" href="/concepts/state">
    Learn how to share state across handlers
  </Card>

  <Card title="Responses" icon="arrow-up-from-bracket" href="/concepts/responses">
    Understand how to return different response types
  </Card>
</CardGroup>
