How to Set Up Redirects in Netlify (_redirects File and netlify.toml)

How to Set Up Redirects in Netlify (_redirects File and netlify.toml)

Perttu Lähteenlahti
Updated March 11, 20265 min read
redirectsrewritesseodeploymentstatic-sites
Share:

Redirects are one of those things you don't think about until you really need them. You've renamed a URL and Google still links to the old one. You're migrating from another platform and all the paths changed. You want /github to point to your repo because the full URL is impossible to remember.

Netlify's redirect system is surprisingly powerful for what looks like a simple config file. You can do basic URL redirects, pattern matching with wildcards, rewrites for SPAs, proxy rules, and even country-based routing. Here's how to use all of it.

Redirects vs. rewrites

Quick distinction before we dive in:

A redirect tells the browser "go here instead." The URL in the address bar changes. You get an HTTP 301 or 302 status code.

A rewrite serves different content without changing the URL. The visitor doesn't know anything happened. You get an HTTP 200 status code.

Netlify uses the same syntax for both. The difference is just the status code.

Where to put your redirects

Two options:

A _redirects file

A plain text file in your publish directory (the folder Netlify deploys — usually public/, dist/, or build/).

/old-page   /new-page   301

Simple, easy to read, and works great for small projects.

netlify.toml

If you prefer everything in one config file:

[[redirects]]
  from = "/old-page"
  to = "/new-page"
  status = 301

Same result, just different syntax. I use netlify.toml when I also need headers, build settings, and other config in the same place.

Common patterns

Rename a page

/blog-old   /blog   301

Use 301 (permanent) when the old URL should never come back. This tells search engines to update their index.

Redirect an entire directory

/docs/*   /documentation/:splat   301

The * matches everything after /docs/, and :splat passes it through. So:

  • /docs/getting-started/documentation/getting-started
  • /docs/api/auth/documentation/api/auth

I've used this pattern for every site migration I've done. It's incredibly useful.

Short URLs to external sites

/github   https://github.com/your-org/your-repo   302

I have a few of these on every project. Way easier to remember than a full GitHub URL.

Status codes matter

301 (Permanent) — "This URL has moved forever. Update your bookmarks." Use this for renamed pages, domain migrations, anything that's not coming back.

302 (Temporary) — "This URL is redirected for now, but might come back." Use this for seasonal pages, A/B tests, or links that point to different places depending on context.

For SEO, the distinction matters. 301s pass link equity to the new URL. 302s don't (in theory — Google is smarter about this now, but 301 is still safer for permanent moves).

SPA rewrites

If you're building a single-page app with React, Vue, or similar — your app handles routing client-side, but Netlify doesn't know that. If someone navigates directly to /dashboard, Netlify looks for a dashboard/index.html file, doesn't find one, and returns a 404.

Fix it with a rewrite:

/*   /index.html   200

This serves index.html for all routes while keeping the URL intact. The 200 status code is what makes it a rewrite instead of a redirect.

Important: put this rule at the bottom of your _redirects file. It's a catch-all, and it'll swallow more specific rules if it comes first.

Rule ordering

Redirects are processed top to bottom. More specific rules need to come first:

/blog/rss   /feed.xml   301
/blog/*     /posts/:splat   301

If you reversed these, /blog/rss would match the wildcard rule and never reach the specific one. When redirects aren't working, ordering is the first thing I check.

Country-based redirects

Netlify can redirect based on the visitor's country (evaluated at the edge, so it's fast):

[[redirects]]
  from = "/"
  to = "/fr"
  status = 302
  conditions = { Country = ["fr"] }

French visitors get sent to /fr, everyone else sees the default page. I've used this for localized landing pages — works really well.

Testing locally

The Netlify CLI runs your site locally with the same routing logic:

netlify dev

This processes redirects and rewrites just like production would. It's the fastest way to catch mistakes before deploying a broken redirect.

Things that bite people

_redirects in the wrong folder. It needs to be in the final build output, not the project root. If your framework builds to dist/, the file needs to end up at dist/_redirects.

Using 301 when you meant 200. This breaks SPA routing. If your React app is showing 301 redirects instead of rendering, you used the wrong status code.

Overlapping wildcards. Always put specific rules before catch-alls. The /* rewrite should be the last line.

Trailing slashes. Netlify's pretty forgiving about this, but inconsistency can cause subtle issues. Pick a convention (trailing slash or no trailing slash) and stick with it.

When to use redirects vs. fixing links

If you control the source code, update the actual links instead of adding a redirect. Redirects are best for:

  • URLs you don't control (external links, search engine results)
  • Migrations from other platforms
  • Backward compatibility with old URL structures
  • Short/branded URLs

Don't use redirects as a crutch for messy internal navigation. Fix the links, then add redirects for the external references you can't control.

Perttu Lähteenlahti

Perttu Lähteenlahti

Developer Advocate at RevenueCat and creator of Netli.fyi. Building on Netlify since 2019. Writes from hands-on experience deploying dozens of production sites.

Manage Netlify on the go

Download Netli.fyi and monitor your sites, check deploys, and manage your projects from anywhere.

Related articles