Configure & deploy site /Static routing /Redirects & rewrites /

Rewrites and proxies

When you assign an HTTP status code of 200 to a redirect rule, it becomes a rewrite. This means that the URL in the visitor’s address bar remains the same, while Netlify’s servers fetch the new location behind the scenes.

This can be useful for single page apps, proxying to other services, proxying to other Netlify sites (internal rewrites), or transitioning for legacy content.

Except where noted, 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.

# Limitations

Rewrites can be very powerful, but there are a few things they cannot do:

  • For security reasons, rewrites between Netlify sites belonging to different teams are not allowed.
  • Infinitely looping rules, where the “from” and “to” resolve to the same location, are incorrect and will be ignored.
  • By default, we limit internal rewrites to one “hop” — you cannot proxy from Netlify SiteA to Netlify SiteB to Netlify SiteC in a single request. This limitation may be amended for customers on a case-by-case basis. Contact support for more information.
  • Proxy rewrite requests will time out after 26 seconds. If you are proxying to a longer-running process, we recommend making an asynchronous request rather than waiting for a response.
  • Rewrites can cause pages that use assets specified through relative paths to load incorrectly. To make sure your site’s proxied content is displayed as expected, use absolute paths for your assets or a <base> tag.
  • Paths handled by proxies or functions may not redirect from HTTP to HTTPS URLs as expected. If you’re working with proxies or functions, we recommend only publishing HTTPS URLs for your visitors to use.
  • While rewrites within the same password-protected site are supported, rewrites to separate password protected sites are not allowed.

# History pushState and single-page apps

If you’re developing a single page app and want the history pushState method to work so you get clean URLs, you’ll want to add the following rewrite rule. If you have other redirect or rewrite rules, this is typically the last rule listed.

/*  /index.html  200
  from = "/*"
  to = "/index.html"
  status = 200

This will effectively serve the index.html instead of giving a 404 no matter what URL the browser requests.

# Shadowing

By default, you can’t shadow a URL that actually exists within the site. This applies to rewrites using a splat or dynamic path segment as well as rewrites for individual routes or files. This means that even if you’ve setup the following rewrite rule:

/*   /index.html   200

The path /partials/chat.html would still render the contents of that file, if that file actually exists. This tends to be the preferred behavior when setting up rewrite rules for single page apps, etc.

If you’re 100% sure that you’ll always want to redirect, even when the URL matches a static file, you can append an exclamation mark to the rule:

/app/*  /app/index.html  200!

This will rewrite everything within /app/* to /app/index.html even if a file matches the URL.

This method can also be applied to individual routes or files:

/best-pets/dogs  /best-pets/cats.html 200!

With the rule above, /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.

# Proxy to another service

Similar to how you can rewrite paths like /* to /index.html, you can also set up rules to let parts of your site proxy to external services. Let’s say you need to communicate from a single-page app with an API on that doesn’t support CORS requests. The following rule will let you use /api/ from your JavaScript client:

/api/*  200

Now all requests to /api/... will be proxied through to straight from our CDN servers without an additional connection from the browser. If the API supports standard HTTP caching mechanisms like ETags or Last-Modified headers, the responses will even get cached by our CDN nodes.

# Custom headers in proxy redirects

For redirect rules specified in the Netlify configuration file, you can add a map with custom headers for your proxy redirects, and Netlify will send the custom headers to another website with every request:

  from = "/search"
  to = ""
  status = 200
  force = true
  headers = {X-From = "Netlify"}

Custom headers apply to the request, not the response

If you are proxying content to your site, custom headers will not be applied to that content.

# Signed proxy redirects

You can use a JSON Web Signature (JWS) to sign all proxy requests to an external URL.

To enable JWS on your requests, Netlify requires a secret token. You can set the token in your site’s environment variables and indicate the variable name as the signed value in the redirect rule. Note that if you have the option to set specific scopes for your environment variables, the scope must include Runtime to be available for signed proxy redirects.

Netlify will inject the environment variable value automatically, so you don’t need to take extra steps to substitute the variable value in the configuration file. Once proxy redirects are added, Netlify will send the JWS as an HMAC HS256 encoded x-nf-sign header to another, non-Netlify website with every proxied request.

Signed proxy redirects must be specified in the Netlify configuration file.

  from = "/search"
  to = ""
  status = 200
  force = true

The JSON document we sign with this JWS header has this format:

  "deploy_context": "production",
  "exp": 1623876755,
  "iss": "netlify",
  "netlify_id": "1be0f471-6532-45ff-b1b1-f9c66ea24dc1",
  "site_url": ""

Signed proxy redirects for external sites only

When proxying from one Netlify application to another, using JWS to sign requests isn’t supported.

# Proxy to another Netlify site

With internal rewrites, you can proxy from one Netlify site to another. If you want to proxy to another Netlify site, we recommend using the site’s subdomain instead of the custom domain in your rewrite rule:

/netlify-site/*  200