Window: popstate event - Web APIs | MDN Skip to main content Skip to search MDN HTML HTML: Markup language HTML reference Elements Global attributes Attributes See all… HTML guides Responsive images HTML cheatsheet Date & time formats See all… Markup languages SVG MathML XML CSS CSS: Styling language CSS reference Properties Selectors At-rules Values See all… CSS guides Box model Animations Flexbox Colors See all… Layout cookbook Column layouts Centering an element Card component See all… JavaScriptJS JavaScript: Scripting language JS reference Standard built-in objects Expressions & operators Statements & declarations Functions See all… JS guides Control flow & error handing Loops and iteration Working with objects Using classes See all… Web APIs Web APIs: Programming interfaces Web API reference File system API Fetch API Geolocation API HTML DOM API Push API Service worker API See all… Web API guides Using the Web animation API Using the Fetch API Working with the History API Using the Web speech API Using web workers All All web technology Technologies Accessibility HTTP URI Web extensions WebAssembly WebDriver See all… Topics Media Performance Privacy Security Progressive web apps Learn Learn web development Frontend developer course Getting started modules Core modules MDN Curriculum Check out the video course from Scrimba, our partner Learn HTML Structuring content with HTML module Learn CSS CSS styling basics module CSS layout module Learn JavaScript Dynamic scripting with JavaScript module Tools Discover our tools Playground HTTP Observatory Border-image generator Border-radius generator Box-shadow generator Color format converter Color mixer Shape generator About Get to know MDN better About MDN Advertise with us Community MDN on GitHub Blog Toggle sidebar Web Web APIs Window popstate Theme OS default Light Dark English (US) Remember language Learn more Deutsch English (US) Español Français 日本語 한국어 Português (do Brasil) Русский 中文 (简体) 正體中文 (繁體) Window: popstate event Baseline Widely available This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015. Learn more See full compatibility The popstate event of the Window interface is fired when the active history entry changes while the user navigates the session history. It changes the current history entry to that of the last page the user visited or, if history.pushState() has been used to add a history entry to the history stack, that history entry is used instead. In this article Syntax Event type Event properties Event handler aliases The history stack When popstate is sent Examples Specifications Browser compatibility See also Syntax Use the event name in methods like addEventListener(), or set an event handler property. js addEventListener("popstate", (event) => { }) onpopstate = (event) => { } Event type A PopStateEvent. Inherits from Event. Event PopStateEvent Event properties PopStateEvent.state Read only Returns a copy of the information that was provided to pushState() or replaceState(). Event handler aliases In addition to the Window interface, the event handler property onpopstate is also available on the following elements: HTMLBodyElement HTMLFrameSetElement SVGSVGElement The history stack If the history entry being activated was created by a call to history.pushState() or was affected by a call to history.replaceState(), the popstate event's state property contains a copy of the history entry's state object. These methods and their corresponding events can be used to add data to the history stack which can be used to reconstruct a dynamically generated page, or to otherwise alter the state of the content being presented while remaining on the same Document. Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event will be triggered by doing a browser action such as a click on the back or forward button (or calling history.back() or history.forward() in JavaScript). Note: When writing functions that process popstate event it is important to take into account that properties like window.location will already reflect the state change (if it affected the current URL), but document might still not. If the goal is to catch the moment when the new document state is already fully in place, a zero-delay setTimeout() method call should be used to effectively put its inner callback function that does the processing at the end of the browser event loop: window.onpopstate = () => setTimeout(doSomeThing, 0); When popstate is sent It's important to first understand that — to combat unwanted pop-ups — browsers may not fire the popstate event at all unless the page has been interacted with. This section describes the steps that browsers follow in the cases where they do potentially fire the popstate event (that is, in the cases where the page has been interacted with). When a navigation occurs — either due to the user triggering the browser's Back button or otherwise — the popstate event is near the end of the process to navigate to the new location. It happens after the new location has loaded (if needed), displayed, made visible, and so on — after the pageshow event is sent, but before the persisted user state information is restored and the hashchange event is sent. To better understand when the popstate event is fired, consider this simplified sequence of events that occurs when the current history entry changes due to either the user navigating the site or the history being traversed programmatically. Here, the transition is changing the current history entry to one we'll refer to as new-entry. The current page's session history stack entry will be referred to as current-entry. If new-entry doesn't currently contain an existing Document, fetch the content and create its Document before continuing. This will eventually send events such as DOMContentLoaded and load to the Window containing the document, but the steps below will continue to execute in the meantime. If current-entry's title wasn't set using one of the History API methods (pushState() or replaceState()), set the entry's title to the string returned by its document.title attribute. If the browser has state information it wishes to store with the current-entry before navigating away from it, it then does so. The entry is now said to have "persisted user state." This information the browser might add to the history session entry may include, for instance, the document's scroll position, the values of form inputs, and other such data. If new-entry has a different Document object than current-entry, the browsing context is updated so that its document property refers to the document referred to by new-entry, and the context's name is updated to match the context name of the now-current document. Each form control within new-entry's Document that has autocomplete configured with its autofill field name set to off is reset. See The HTML autocomplete attribute for more about the autocomplete field names and how autocomplete works. If new-entry's document is already fully loaded and ready—that is, its readyState is complete—and the document is not already visible, it's made visible and the pageshow event is fired at the document with the PageTransitionEvent's persisted attribute set to true. The document's URL is set to that of new-entry. If the history traversal is being performed with replacement enabled, the entry immediately prior to the destination entry (taking into account the delta parameter on methods such as go()) is removed from the history stack. If the new-entry doesn't have persisted user state and its URL's fragment is non-null, the document is scrolled to that fragment. Next, current-entry is set to new-entry. The destination entry is now considered to be current. If new-entry has serialized state information saved with it, that information is deserialized into History.state; otherwise, state is null. If the value of state changed, the popstate event is sent to the document. Any persisted user state is restored, if the browser chooses to do so. If the original and new entries shared the same document, but had different fragments in their URLs, send the hashchange event to the window. As you can see, the popstate event is nearly the last thing done in the process of navigating pages in this way. Examples A page at http://example.com/example.html running the following code will generate logs as indicated: js window.addEventListener("popstate", (event) => { console.log( `location: ${document.location}, state: ${JSON.stringify(event.state)}`, ); }); history.pushState({ page: 1 }, "title 1", "?page=1"); history.pushState({ page: 2 }, "title 2", "?page=2"); history.replaceState({ page: 3 }, "title 3", "?page=3"); history.back(); // Logs "location: http://example.com/example.html?page=1, state: {"page":1}" history.back(); // Logs "location: http://example.com/example.html, state: null" history.go(2); // Logs "location: http://example.com/example.html?page=3, state: {"page":3}" The same example using the onpopstate event handler property: js window.onpopstate = (event) => { console.log( `location: ${document.location}, state: ${JSON.stringify(event.state)}`, ); }; history.pushState({ page: 1 }, "title 1", "?page=1"); history.pushState({ page: 2 }, "title 2", "?page=2"); history.replaceState({ page: 3 }, "title 3", "?page=3"); history.back(); // Logs "location: http://example.com/example.html?page=1, state: {"page":1}" history.back(); // Logs "location: http://example.com/example.html, state: null" history.go(2); // Logs "location: http://example.com/example.html?page=3, state: {"page":3}" Note that even though the original history entry (for http://example.com/example.html) has no state object associated with it, a popstate event is still fired when we activate that entry after the second call to history.back(). Specifications Specification HTML # event-popstate HTML # handler-window-onpopstate Browser compatibility Enable JavaScript to view this browser compatibility table. See also Manipulating the browser history (the History API) Window: hashchange event Help improve MDN Was this page helpful to you? Yes No Learn how to contribute This page was last modified on Mar 9, 2026 by MDN contributors. View this page on GitHub • Report a problem with this content Filter sidebar Clear filter input History API Window Instance properties caches closed cookieStore crashReport credentialless crossOriginIsolated crypto customElements devicePixelRatio document documentPictureInPicture event external fence frameElement frames fullScreen history indexedDB innerHeight innerWidth isSecureContext launchQueue length localStorage location locationbar menubar mozInnerScreenX mozInnerScreenY name navigation navigator opener orientation origin originAgentCluster outerHeight outerWidth parent performance personalbar scheduler screen screenLeft screenTop screenX screenY scrollbars scrollMaxX scrollMaxY scrollX scrollY self sessionStorage sharedStorage speechSynthesis status statusbar toolbar top trustedTypes viewport visualViewport window Instance methods alert() atob() blur() btoa() cancelAnimationFrame() cancelIdleCallback() captureEvents() clearImmediate() clearInterval() clearTimeout() close() confirm() createImageBitmap() dump() fetch() fetchLater() find() focus() getComputedStyle() getDefaultComputedStyle() getScreenDetails() getSelection() matchMedia() moveBy() moveTo() open() postMessage() print() prompt() queryLocalFonts() queueMicrotask() releaseEvents() reportError() requestAnimationFrame() requestFileSystem() requestIdleCallback() requestResize() resizeBy() resizeTo() scroll() scrollBy() scrollByLines() scrollByPages() scrollTo() setImmediate() setInterval() setResizable() setTimeout() showDirectoryPicker() showOpenFilePicker() showSaveFilePicker() sizeToContent() stop() structuredClone() webkitConvertPointFromNodeToPage() webkitConvertPointFromPageToNode() Events afterprint appinstalled beforeinstallprompt beforeprint beforeunload blur devicemotion deviceorientation deviceorientationabsolute error focus gamepadconnected gamepaddisconnected hashchange languagechange load message messageerror offline online orientationchange pagehide pagereveal pageshow pageswap popstate rejectionhandled resize scrollsnapchange scrollsnapchanging storage unhandledrejection unload vrdisplayactivate vrdisplayconnect vrdisplaydeactivate vrdisplaydisconnect vrdisplaypresentchange Inheritance EventTarget Related pages for History API History PopStateEvent Window.history Guides Working with the History API MDN Your blueprint for a better internet. MDN About Blog Mozilla careers Advertise with us MDN Plus Product help Contribute MDN Community Community resources Writing guidelines MDN Discord MDN on GitHub Developers Web technologies Learn web development Guides Tutorials Glossary Hacks blog Mozilla Website Privacy Notice Telemetry Settings Legal Community Participation Guidelines Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.