Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild
Back to Blog Troubleshooting

Netlify React App Page Not Found: Why the 404 Appears on Refresh and the Two-Line Fix

Sean

Platform Writer

Sep 14, 2026
7 min read

A React app deployed to Netlify shows Page Not Found when you refresh on any route except the homepage, or when someone opens a shared link, because the host is looking for a file at that path and there is none. The router only exists inside index.html, which the browser never loaded. The fix is a single rewrite rule that serves index.html for every path with a 200 status: a _redirects file containing /* /index.html 200, placed so it ends up in the publish directory. If the 404 appears on the homepage too, the problem is the publish directory or a failed build, not routing.

Netlify React App Page Not Found: Why the 404 Appears on Refresh and the Two-Line Fix

This is the most-asked deployment question for React, and the accepted answer has been the same two lines for years. The interesting part is not the fix but why it is needed, because understanding that is what lets you fix the same problem on every other static host, diagnose the cases where the two lines do not help, and decide whether the hash-router workaround someone will suggest is worth its cost. It is not.

Table of contents

Why it happens

A single-page app is one HTML file and a bundle of JavaScript. Navigation inside the app is handled by the router in that bundle: clicking a link to /dashboard updates the URL bar and swaps components, and no request for /dashboard ever reaches the server. The server has never heard of /dashboard.

Then someone refreshes, or opens the link from a message. The browser sends a real request for /dashboard to the host. The host looks for dashboard/index.html or dashboard.html in the published folder, finds nothing, and returns its 404 page. The app never gets a chance to run. Every static host behaves this way, because serving files is what a static host does. The fix is to tell it that, for this site, every path should serve the one file that contains the app.

Fix one: the _redirects file

Create a file named _redirects, no extension, with this single line:

/*    /index.html   200

The 200 is the important part. It makes this a rewrite, not a redirect: the URL stays /dashboard, the content served is index.html, and the router in the bundle reads the URL and renders the right page. A 301 or 302 would change the URL to / and lose the route.

The file has to end up in the folder Netlify publishes, next to the built index.html. For Create React App and Vite that means putting it in public/, which the build copies into build/ or dist/ respectively. Putting it in the project root does nothing, which is the most common reason the fix appears not to work. Redeploy after adding it; the rule is read at deploy time.

Fix two: netlify.toml

The same rule can live in netlify.toml at the repository root, which some teams prefer because it keeps deploy configuration in one file:

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

Use one or the other, not both. If both exist, rules in _redirects are processed first, which is fine for this case but confusing when the two files disagree about something else later.

When it is not routing at all

If the homepage itself shows Page Not Found, no rewrite rule will help, because the host cannot find index.html either. The support guide for this case lists the usual suspects, and they are all about what got published, not how it is routed.

  • Wrong publish directory. Create React App builds to build/; Vite builds to dist/. If the site settings say one and the tool produces the other, the deploy is an empty folder or the raw source.
  • The build failed and the last successful deploy is stale, or there has never been one. Read the deploy log before anything else.
  • A base or homepage setting that prefixes asset paths, so index.html loads but every script 404s and the page is blank rather than not found.
  • Case-sensitive filenames. Logo.png on a laptop that does not care becomes a 404 on a server that does.
  • A stale cached copy in the browser. The hard refresh post covers when that is the actual problem and when it is a distraction.

The sequence that works: open the deploy log, confirm the build succeeded, confirm the publish directory contains index.html, then and only then add the rewrite rule.

Hash router: the fix that is not one

Someone will suggest switching to a hash router so URLs look like /#/dashboard. It works, because the part after # never reaches the server, so every request is for / and the 404 disappears. It also gives up clean URLs, makes every route invisible to search engines and link previews, breaks server-side analytics on paths, and solves a hosting configuration problem by changing the application. One line in a text file is the better trade in every case except a demo that will never have a public URL.

The same problem on every static host

The rewrite rule is not a Netlify idea. It is the single-page-app fallback, and every static host has a version of it: a rewrite in a config file, a catch-all in a web server block, or a toggle in a dashboard. The symptoms are identical everywhere, which is why a team that understands the cause fixes it in a minute on the next platform and a team that memorised the two lines opens a support thread.

On RunxBuild static sites, the fallback is a setting rather than a file: the SPA fallback option serves index.html for unmatched paths with a 200, and the rewrites docs cover the general form when a site needs more than the catch-all. The site builds from the repository on push, with the build log in the dashboard for the cases above where the folder was the problem, and 120GB of bandwidth is included. The React SEO post picks up the other consequence of client-side routing: the pages are there for users and invisible to crawlers until you do something about it.

How this fits the rest of the stack

Page Not Found on a React app is the host doing its job on a request the app was never designed to receive. Serve index.html for every path with a 200, from a _redirects file in public/ or a rule in netlify.toml, and let the router take it from there. If the homepage 404s too, fix the publish directory first. The RunxBuild hosting calculator shows what a static single-page app costs to host with the fallback handled, which for most React apps is the bandwidth line and nothing else. Ship the fix, then go read the deploy log anyway.

Useful related references:

FAQ

Why does my React app show Page Not Found on refresh?

Because a refresh sends a real request for the current path to the host, and a single-page app has no file at that path. The router that knows about the route lives inside index.html, which was never loaded. A rewrite rule that serves index.html for every path with a 200 status fixes it.

Where does the _redirects file go?

In the folder that gets published, next to the built index.html. For Create React App and Vite that means the public/ folder, which the build copies into build/ or dist/. A _redirects file in the project root is ignored.

Does the 200 rewrite hurt SEO?

Not by itself. Every path returns the same HTML with a 200, which is exactly what crawlers expect from a single-page app. What hurts SEO is that the content is rendered by JavaScript after load; that is a separate problem solved by pre-rendering or server rendering, not by the rewrite rule.

Why does it work locally but not after deploying?

The dev server includes the single-page-app fallback by default, so every path serves index.html on your laptop. A static host does not assume that, because most sites are not single-page apps. The rewrite rule tells the host what the dev server already knew.

Should I use a hash router instead?

No, unless the app will never have public URLs. A hash router hides the route from the server so the 404 goes away, but it also hides it from search engines, link previews and analytics, and it changes the application to work around a one-line hosting setting.

#netlify react app page not found#netlify 404 on refresh#react router netlify#spa fallback#_redirects netlify