The popstate event of the Window interface is fired when the active history entry changes.

Bubbles Yes
Cancelable No
Interface PopStateEvent
Event handler property onpopstate

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.

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).

Browsers tend to handle the popstate event differently on page load. Chrome (prior to v34) and Safari always emit a popstate event on page load, but Firefox doesn't.

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);

Examples

A page at http://example.com/example.html running the following code will generate logs as indicated:

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:

window.onpopstate = function(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 Status
HTML Living Standard
The definition of 'popstate' in that specification.
Living Standard

Browser compatibility

No compatibility data found. Please contribute data for "api.Window.popstate_event" (depth: 1) to the MDN compatibility data repository.

Browsers used to handle the popstate event differently on page load, but now they behave the same. Firefox never emitted a popstate event on page load. Chrome did until version 34, while Safari did until version 10.0.

See also