---
title: "Redirect options"
description: "Understand redirect rule options to customize how site paths are matched and redirected."
---

> For the complete documentation index for AI agents, see [llms.txt](https://docs.netlify.com/llms.txt). Markdown versions of any documentation page are available by appending `.md` to its docs.netlify.com URL.

Netlify's redirect rules accept a number of options to customize how the paths are matched and redirected. Most of the examples on this page use the [`_redirects` file syntax](/manage/routing/redirects/overview#syntax-for-the-_redirects-file), but all of these options are available in the [Netlify configuration file syntax](/manage/routing/redirects/overview#syntax-for-the-netlify-configuration-file) as well.

## HTTP status codes

HTTP status codes are sent in server responses to the client or browser. The code gives information about the type of response.

You can specify the HTTP status code for any redirect rule. If left unspecified, the default is `301`.

Here are some examples of status codes you might use:

- **`301`** (default)**:** permanent redirect code. Tells the client that the address for this resource has permanently changed, and any indexes using the old address should start using the new one. The URL in the browser address bar will display the new address.
- **`302`:** temporary redirect code. Use this status code instead of `307`, which is currently unsupported. Tells the client that the current address change is temporary. The URL in the browser address bar will display the new address.
- **`404`:** not found code. You can use this status code to present [custom 404 pages](/manage/routing/redirects/redirect-options#custom-404-page-handling) when visitors access paths on your site that don't exist. With this status code, the page content will change, but the URL in the browser address bar will not.
- **`200`:** OK code. Redirects with this status code will change the server response without changing the URL in the browser address bar. This is used for [rewrites and proxying](/manage/routing/redirects/rewrites-proxies).

Here are some example redirect rules with status codes:

### Tabs Component:

<TabItem label="_redirects">
```
# Redirect with a 301
/home         /              301

# Redirect with a 302
/my-redirect  /              302

# Show a custom 404 for this path
/ecommerce    /store-closed  404

# Rewrite a path
/pass-through /index.html    200
```
</TabItem>

<TabItem label="netlify.toml">
```toml
# Redirect with a 301
[[redirects]]
from = "/home"
to = "/"
status = 301

# Redirect with a 302
[[redirects]]
from = "/my-redirect"
to = "/"
status = 302

# Show a custom 404 for this path
[[redirects]]
from = "/ecommerce"
to = "/store-closed"
status = 404

# Rewrite a path
[[redirects]]
from = "/pass-through"
to = "/index.html"
status = 200
```
</TabItem>

## Custom 404 page handling

You can set up a custom 404 page for all paths that don't resolve to a static file. This doesn't require any redirect rules. If you add a `404.html` page to your site, it will be picked up and displayed automatically for any failed paths.

You can also use this in combination with other features of our redirects by creating explicit entries for different paths:

### Tabs Component:

<TabItem label="_redirects">
```
/en/* /en/404.html 404
/de/* /de/404.html 404
```
</TabItem>

<TabItem label="netlify.toml">
```toml
[[redirects]]
from = "/en/*"
to = "/en/404.html"
status = 404

[[redirects]]
from = "/de/*"
to = "/de/404.html"
status = 404
```
</TabItem>

Due to [the shadowing behavior](/manage/routing/redirects/rewrites-proxies#shadowing) in our redirects system, the 404 pages will only be returned for nonexistent assets under the above paths.

## Force redirects 

There are times where a redirect will not happen because a file will match a URL path. In these cases, you can force the redirect to happen with either a `!` appended to your status code (for `_redirects`) or setting the `force` attribute to be true (on `netlify.toml`).

For example:

### Tabs Component:

<TabItem label="_redirects">
```
/best-pets/dogs  /best-pets/cats.html 200!
```
</TabItem>

<TabItem label="netlify.toml">
```toml
[[redirects]]
from = "/best-pets/dogs"
to = "/best-pets/cats.html"
status = 200
force = true
```
</TabItem>

In this forced redirect example, `/best-pets/dogs` will always display the content in `/best-pets/cats.html` even if there is a file at `/best-pets/dogs/index.html`. 

Learn more in our docs on [shadowing](/manage/routing/redirects/rewrites-proxies#shadowing).

## Splats

An asterisk indicates a **splat** that will match anything that follows it.

You can use the splat in your rewrites or redirects like this:

### Tabs Component:

<TabItem label="_redirects">
```
/news/*  /blog/:splat
```
</TabItem>

<TabItem label="netlify.toml">
```toml
[[redirects]]
from = "/news/*"
to = "/blog/:splat"
```
</TabItem>

This would redirect paths like `/news/2004/01/10/my-story` to `/blog/2004/01/10/my-story`.

The redirect engine processes the [first matching rule](/manage/routing/redirects/overview#rule-processing-order) it finds, so more specific rules should be listed before more general ones:

### Tabs Component:

<TabItem label="_redirects">
```
# This will redirect /jobs/customer-ninja-rockstar
/jobs/customer-ninja-rockstar  /careers/support-engineer

# This will redirect all paths under /jobs except the path above
/jobs/*                        /careers/:splat

# This will never trigger, because the rule above will trigger first
/jobs/outdated-job-link        /careers/position-filled
```
</TabItem>

<TabItem label="netlify.toml">
```toml
# This will redirect /jobs/customer-ninja-rockstar
[[redirects]]
from = "/jobs/customer-ninja-rockstar"
to = "/careers/support-engineer"

# This will redirect all paths under /jobs except the path above            
[[redirects]]
from = "/jobs/*"
to = "/careers/:splat"

# This will never trigger, because the rule above will trigger first
[[redirects]]
from = "/jobs/outdated-job-link"
to = "/careers/position-filled"
```
</TabItem>

There are two limitations to be aware of when you use splats:
- It's not possible to use an asterisk as a wildcard in the middle of a path, for example `/jobs/*.html`. You can only use asterisks at the end of the path segment, such as `/jobs/*`.
- It's not possible to indicate a path to exclude from a splat redirect rule. Instead, we recommend that you take advantage of the [rule processing order](/manage/routing/redirects/overview#rule-processing-order) to set a more specific rule for the path that you want to exclude.

Note that Netlify processes wildcards (`*`) in headers differently than those used in redirects. Learn more about [how to use wildcards in headers](/manage/routing/headers#wildcards-and-placeholders-in-paths). 

## Placeholders

You can use placeholders in the origin and target paths:

```
/news/:month/:date/:year/:slug  /blog/:year/:month/:date/:slug
```

This would redirect a URL like `/news/02/12/2004/my-story` to `/blog/2004/02/12/my-story`. A placeholder either matches a path segment from one `/` to the next `/` or matches a final path segment including a file extension but excluding a query string.

Note that Netlify processes placeholders in headers differently than those used in redirects. Learn more about [how to use placeholders in headers](/manage/routing/headers#wildcards-and-placeholders-in-paths). 

## Query parameters

You can also use query parameters to more finely control your URL matches.

While our service automatically passes on all query string parameters to destination paths for redirects with `200`, `301`, and `302` HTTP status, you can also choose to define a redirect path based on a specific parameter or combination of parameters.

The following match redirects a URL like: `/store?id=my-blog-post` to `/blog/my-blog-post` with a `301` redirect. This affects request URLs with an `id` query parameter only.

```
/store id=:id  /blog/:id  301
```

Note that this rule matches only URLs that have only the `id` parameter and no others. If the URL contains other parameters in addition to or instead of `id`, the request doesn't match that rule.

To match more than one query parameter, add separate key/value pairs separated by space:

```
/articles id=:id tag=:tag /posts/:tag/:id 301
```

If you have multiple parameters, some of which are optional, this is the pattern to follow to ensure that we are prepared to handle all possibilities. Note that the most general redirect is _after_ the more specific ones:

```
# Both values - ordering from the browser doesn't matter; this will cover either.
/path/* param1=:value1 param2=:value2 /otherpath/:value1/:value2/:splat 301

# One value or the other.  Must match exactly.
/path/* param1=:value1 /otherpath/:value1/:splat 301
/path/* param2=:value2 /otherpath/:value2/:splat 301

# Base case, when no params are passed.  
# Our system forwards all query params to the /otherpath URL if this is the only rule.  
# Otherwise it matches all requests not matched in a prior rule for the same path such as the ones above.
/path/* /otherpath/:splat 301
```

## Trailing slash

Our CDN edge nodes do URL normalization before the redirect rules kick in. This happens to make sure we can guarantee the highest possible cache hit rate and the absolute best performance for your site. 

What this means for your redirect rules is that Netlify will match paths to rules regardless of whether or not they contain a trailing slash.

```
# These rules are effectively the same:
# either rule alone would trigger on both paths
/blog/title-with-a-typo    /blog/typo-free-title
/blog/title-with-a-typo/   /blog/typo-free-title

# This rule will cause an infinite redirect
# because the paths are effectively the same
/blog/remove-my-slashes/   /blog/remove-my-slashes  301!
```

### Note - Using a proxy?

Netlify normalizes URLs by removing the trailing slash but not for internal rewrites. For example, if your route is handled by Site B but is requested as a rewrite on Site A, such as with `/old-path https://siteb.netlify.app/new-path 200` in your `_redirects` file, then normalization will not necessarily be applied.

You cannot use a redirect rule to add or remove a trailing slash. However, you _can_ rely on Netlify's **Pretty URLs** feature, which is enabled by default for sites and standardizes your URLs. 

When Pretty URLs are enabled, Netlify forwards paths like `/about` to `/about/` (a common practice in static sites and single-page apps) and rewrites paths like `/about.html` to `/about/`.

Learn more about using Pretty URLs in this [official Support Guide](https://answers.netlify.com/t/support-guide-how-can-i-alter-trailing-slash-behaviour-in-my-urls-will-enabling-pretty-urls-help/31191).

To check if Pretty URLs are enabled for your site go to 
### NavigationPath Component:

Project configuration > Developer settings > Post processing > Pretty URLs
.

## Domain-level redirects

All of the examples so far assume configuration for all domains assigned to the site, using the specified paths. If instead you need to do something special for a specific domain alias or protocol (HTTP vs HTTPS), you'll want a pattern more like this one:

```
# http and https need separate rules if you don't force_ssl!
http://blog.yoursite.com/* https://www.yoursite.com/blog/:splat 301!
https://blog.yoursite.com/* https://www.yoursite.com/blog/:splat 301!

# other URLS might proxy or redirect offsite
https://frontend.yoursite.com/login/* https://backend.yoursite.com/:splat 200
```

Refer to the [note on shadowing](/manage/routing/redirects/rewrites-proxies#shadowing) for the reasoning behind the `!` - it is presumably the case that you have a `/blog/index.html` that you'd rather serve than your site's main `index.html` in this case!

### Caution - Domains must be assigned to the site

For Netlify to redirect from a domain that is not the site's main custom domain, the domain must be assigned to the site - probably as a [domain alias](/manage/domains/domains-fundamentals/domains-glossary#domain-aliases) or a [branch subdomain](/manage/domains/domains-fundamentals/domains-glossary#branch-subdomain).

## Redirect by country or language

For large multi-regional or multi-lingual sites, you may want to send site visitors to different content based on their location (by country GeoIP data) or their browser's language configuration.

Netlify can handle these requests with GeoIP- and language-based redirects directly from our CDN nodes.

Both the language and the country can be specified in a cookie as well (`nf_lang` and `nf_country` respectively), so you can override the default behavior with JavaScript.

When you add these redirect rules, Netlify automatically creates alternate headers to enable the redirection in our CDN nodes. This removes the need for a round trip to our origin servers and ensures that normal pages, besides country or language based redirects, are cached on the CDN nodes.

Here are some examples:

```
# Redirect users in Australia or New Zealand to /anz.
# There CANNOT be spaces in the last parameter: Country=x,y,z or Language=xx,yy
/  /anz     302  Country=au,nz
# Redirect users in Israel to /israel
/  /israel  302  Country=il

# Redirect users with Hebrew language preference from /israel to /israel/he
/israel/*  /israel/he/:splat  302  Language=he
```

The system is smart enough to flatten chains of redirect. In the above case, if a user in Israel with Hebrew language preference visits `/`, they'll get redirected directly to `/israel/he` in one step. Our cache server will cache this redirect for any other users that would match the same country and language rules.

The `Country` attribute accepts [ISO 3166-1 alpha-2 country codes](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements).

The `Language` attribute accepts [standard browser language identification codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) and locale codes that combine language and country. Here is an example that uses both:

```
/products /en-us/products 301! Language=en-us
/products /en/products 301! Language=en
```

Users with `en-us` preference for English United States match the first rule and get redirected to `/en-us/products`. Users with any other `en-*` English language preference, such as `en-au` for English Australia, match the second rule and get redirected to `/en/products`. Users with non-English language preference, such as no language preference or `he` for Hebrew, get served the originally requested page `/products`.

### Caution - Language quality values ignored

Language-based redirects always match against the first language reported by the browser in the `Accept-Language` header regardless of quality value weighting.

For more examples and guidance on setting redirects by country or language, check out our blog post on [country-based redirects](https://www.netlify.com/blog/2021/11/05/how-to-internationalize-sites-with-country-based-redirects/).

## Redirect by role

Role-based redirects let you restrict access to certain paths of your application to logged-in visitors with certain roles, as authorized by Netlify Identity or any authentication provider that supports JSON Web Tokens (JWT). (Role-based redirects using external authentication providers is available on Enterprise [plans](https://www.netlify.com/pricing/).) 

This access control is implemented at our CDN edge, removing the need for a round trip to our origin servers.

For more information, visit the page on [Role-based access control](/manage/security/secure-access-to-sites/role-based-access-control).

## Redirect by cookie presence

You may want to send site visitors to different content based on the HTTP cookies included in their incoming request.

Cookie-based redirects allow you to send visitors content based on whether a specific HTTP cookie exists in the request or not, regardless of its value. This condition checks the cookie name in a case-insensitive way. To match multiple cookies, include them in a list separated by commas.

For example:

### Tabs Component:

<TabItem label="_redirects">
```
# Forward requests to /legacy if the browser sends a cookie 
# named `is_legacy` or `my_other_cookie`
/* /legacy/:splat 200 Cookie=is_legacy,my_other_cookie
```
</TabItem>

<TabItem label="netlify.toml">
```toml
# Forward requests to /legacy if the browser sends a cookie 
# named `is_legacy` or `my_other_cookie`
[[redirects]]
from = "/*"
to = "/legacy/:splat"
status = 200
conditions = {Cookie = ["is_legacy","my_other_cookie"]}
```
</TabItem>

