Static routing /Redirects & rewrites /

Redirect options

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, but all of these options are available in the Netlify configuration file syntax 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 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.

Here are some example redirect rules with status codes:

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

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

/en/* /en/404.html 404
/de/* /de/404.html 404
[[redirects]]
from = "/en/*"
to = "/en/404.html"
status = 404

[[redirects]]
from = "/de/*"
to = "/de/404.html"
status = 404

Due to the shadowing behavior 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:

/best-pets/dogs  /best-pets/cats.html 200!
[[redirects]]
from = "/best-pets/dogs"
to = "/best-pets/cats.html"
status = 200
force = true

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.

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

/news/*  /blog/:splat
[[redirects]]
from = "/news/*"
to = "/blog/:splat"

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 it finds, so more specific rules should be listed before more general ones:

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

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

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

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

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.

To check if Pretty URLs are enabled for your site go to

.

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

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 or a 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.

The Language attribute accepts standard browser language identification 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.

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.

# 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 Core Enterprise plans.)

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.

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:

# 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
# 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"]}

Edge Functions