What is the History API?
The History API lets JavaScript change the URL and back button without a reload. How pushState, replaceState and popstate work, plus SEO traps.
What is the History API?
The History API is a browser interface, exposed as window.history, that lets JavaScript move through the session history and add or change entries. With pushState() and replaceState() a page can update the address bar and the back button without a full reload, which is how a single-page app gives every screen its own URL.
How it works
history.back(),history.forward()andhistory.go(n)move through existing entries, like the browser buttons.history.lengthis the number of entries.history.pushState(state, "", url)adds a new entry.history.replaceState(state, "", url)overwrites the current one instead.stateis any serializable object stored with the entry. The second argument is unused but cannot be left out, so pass an empty string.urlis optional and must be the same origin as the current page, otherwise the call throws aSecurityError.- Neither method loads the URL or checks that it exists. They only change what the browser records and shows.
- The
popstateevent fires when the user moves through history (back, forward,go()). CallingpushState()orreplaceState()does not fire it, and browsers may skip it until the page has been interacted with.
The MDN reference for pushState() documents the details.
A minimal router
Navigation calls pushState and renders the view itself. Back and forward trigger popstate, and the handler renders the view for the URL the browser has restored:
function navigate(path) {
history.pushState({ path: path }, "", path);
render(path);
}
window.addEventListener("popstate", function () {
render(location.pathname);
});
The renderer works on the DOM in place, so no new document is requested.
The server still has to answer those URLs
A URL created with pushState is only a record in the browser. If a visitor reloads on /products/42, bookmarks it or follows a shared link, the server receives that request. It must return the app (or real content) for it, not a 404. MDN notes the browser will not load the URL after pushState(), but may load it later, for instance after a restart.
SEO and crawlers
Google's guidance for JavaScript sites is to use the History API for routing between views and not to use URL fragments to load different content. Links must be real <a href="..."> elements: crawlers find links through the href, and a click handler on a span or an anchor without href gives them nothing to follow. Error views also need care, because a client-routed 404 page still returns status 200 unless you redirect to a URL that returns a real 404 or add a noindex robots tag. See Google's JavaScript SEO basics.
Common mistakes
- No
popstatehandler. The URL changes on Back but the screen does not. - Links without
href. They work in the browser and are invisible to crawlers, and middle-click and "open in new tab" break. - Hash routing for content. Fragment URLs are not reliably resolved by crawlers.
- Large state objects. Some browsers cap the serialized size and throw. Keep state small and use
sessionStoragefor more. - Expecting the title to change. The second argument is ignored, so set
document.titleyourself and move focus for screen-reader users. - No server fallback. Deep links return 404 on reload.
How it relates to testing and monitoring
A pushState navigation usually does not request a new HTML page. The cost sits in the API calls and rendering that follow, so a test that only fetches HTML misses most of it. Test the API calls the app makes, weighted the way users make them: see load testing single page applications and run them with load testing. API monitoring keeps watching the endpoints behind your routes, and synthetic monitoring covers whole journeys. Note that deep URLs should also be checked directly: a request for a route URL should return 200 from the server, not only work after in-app navigation.
FAQ: History API
Does pushState reload the page?
No. It adds a history entry and changes the URL shown in the address bar, but the browser does not load that URL and does not check that it exists.
Does pushState trigger the popstate event?
No. popstate fires when the active history entry changes through user navigation, such as Back, Forward or history.go(). After your own pushState call you update the view yourself.
What is the difference between pushState and replaceState?
pushState adds a new entry, so Back returns to the previous one. replaceState overwrites the current entry, so no extra Back step is created. Use replace for corrections such as redirects or updating a filter in the URL.
Should I use hash routing or the History API?
For content that should be indexed, use the History API with real paths. Google advises against using URL fragments to load different content. Hash routing needs no server configuration, which can suit internal tools that do not need search traffic.
Do I need server configuration for History API routes?
Yes. The server must answer every route URL, usually by returning the app shell or pre-rendered content, because a reload, bookmark or shared link requests that URL directly.
Related terms
- What is Idempotency? HTTP Methods, Idempotency Keys, Examples
- What is JSON? Beginner's Guide with Syntax, Examples
- What is JSON-RPC? Protocol, Examples, REST Comparison
- What is multipart/form-data Content-Type? File Uploads, Examples
- What is Swagger? Swagger vs OpenAPI Explained
- CRUD Operations: Create, Read, Update, Delete Explained
- What Are API Attacks?
- What Are API Cookies? Definition and Security
Related LoadFocus Tools
Put this concept into practice with LoadFocus, the same platform that powers everything you just read about.