> ## 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.

# Path

> Extract and deserialize path parameters from the URL

Extractor that will get captures from the URL and parse them using `serde`.

Any percent encoded parameters will be automatically decoded. The decoded parameters must be valid UTF-8, otherwise `Path` will fail and return a `400 Bad Request` response.

## Type signature

```rust theme={null}
pub struct Path<T>(pub T);
```

## Usage

### Single parameter

If the path contains only one parameter, you can omit the tuple:

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

async fn user_info(Path(user_id): Path<Uuid>) {
    // user_id is a Uuid
}

let app = Router::new().route("/users/{user_id}", get(user_info));
```

### Multiple parameters with tuple

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

async fn users_teams_show(
    Path((user_id, team_id)): Path<(Uuid, Uuid)>,
) {
    // user_id and team_id are both Uuid
}

let app = Router::new()
    .route("/users/{user_id}/team/{team_id}", get(users_teams_show));
```

### Multiple parameters with struct

Path segment labels will be matched with struct field names:

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

#[derive(Deserialize)]
struct Params {
    user_id: Uuid,
    team_id: Uuid,
}

async fn users_teams_show(
    Path(Params { user_id, team_id }): Path<Params>,
) {
    // use user_id and team_id
}

let app = Router::new()
    .route("/users/{user_id}/team/{team_id}", get(users_teams_show));
```

### Capturing all parameters

You can use `HashMap` or `Vec` to capture all path parameters:

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

async fn params_map(
    Path(params): Path<HashMap<String, String>>,
) {
    // params contains all path parameters as key-value pairs
}

async fn params_vec(
    Path(params): Path<Vec<(String, String)>>,
) {
    // params contains all path parameters as tuples
}

let app = Router::new()
    .route("/users/{user_id}/team/{team_id}", 
           get(params_map).post(params_vec));
```

## Error handling

<ParamField path="Rejection" type="PathRejection">
  Returned when path parameters cannot be deserialized into the target type.
</ParamField>

### Error kinds

The `PathRejection` type contains an `ErrorKind` enum with detailed error information:

* `WrongNumberOfParameters` - The URI contained a different number of parameters than expected
* `ParseErrorAtKey` - Failed to parse a value at a specific key (for structs)
* `ParseErrorAtIndex` - Failed to parse a value at a specific index (for tuples)
* `ParseError` - Failed to parse a value (for primitives)
* `InvalidUtf8InPathParam` - A parameter contained invalid UTF-8 after percent decoding
* `UnsupportedType` - Attempted to deserialize into an unsupported type
* `DeserializeError` - Custom deserialization error

### Customizing rejections

See the [customize-path-rejection](https://github.com/tokio-rs/axum/blob/main/examples/customize-path-rejection/src/main.rs) example for how to provide custom error responses.

## Optional path parameters

You can use `Option<Path<T>>` to allow the same handler to be used in routes with and without parameters:

```rust theme={null}
async fn handler(path: Option<Path<String>>) {
    match path {
        Some(Path(param)) => {
            // Route had a parameter
        }
        None => {
            // Route had no parameters
        }
    }
}
```

## Percent decoding

Path parameters are automatically percent decoded. For example, `%20` becomes a space:

```rust theme={null}
// GET /files/my%20document.pdf
async fn handler(Path(filename): Path<String>) {
    // filename = "my document.pdf"
}
```

## Raw path parameters

For lower-level access without deserialization, use `RawPathParams`:

```rust theme={null}
use axum::extract::RawPathParams;

async fn handler(params: RawPathParams) {
    for (key, value) in &params {
        println!("{key} = {value}");
    }
}
```
