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

# 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

Due to the shadowing behavior in our redirects system, the 404 pages will only be returned for nonexistent assets under the above paths.

# 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

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

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

# 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

Query parameter changes

Query parameters are now passed by default to the destination path even if they aren’t specified in a redirect rule. Visit our Support Forums to learn more about this change to redirects with query string parameters.

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

You cannot use a redirect rule to add or remove a trailing slash. However, you can enable Netlify’s Pretty URLs feature in Site settings > Build & deploy > Post processing > Asset optimization.

In addition to forwarding paths like /about to /about/ (a common practice in static sites and single-page apps), it will also rewrite paths like /about.html to /about/.

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

# other URLS might proxy or redirect offsite* 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 country codes.

The Language attribute accepts standard browser language identification codes.

General and regional language codes

General language codes will match all regional variations. For example, en will match en-US and en-GB; zh will match zh-tw and zh-hk, etc.

# 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 may not be available on all 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`
    from = "/*"
    to = "/legacy/:splat"
    status = 200
    conditions = {Cookie = ["is_legacy","my_other_cookie"]}

    Edge Handlers