Browser support for the Page Lifecycle API
Which browsers send visibilitychange, pagehide, pageshow, freeze and resume, how Chromium, Firefox and WebKit order the listeners, and the sources of each fact.
The facts on this page come from the research of the lag project on 2026-10-07 (browser support, local experiments).
The events and the properties
| Feature | API | Chromium | Firefox | Safari |
|---|---|---|---|---|
| Page visibility | visibilitychange, document.visibilityState | Yes | Yes | Yes |
| Back/forward cache events | pagehide, pageshow, persisted | Yes | Yes | Yes |
| Page Lifecycle | freeze, resume, document.wasDiscarded | 68 (Edge 79) | No | No |
| Visibility-state entries | visibility-state performance entries | 115 | No | No |
| Not-restored reasons | notRestoredReasons | 123 (gradual rollout) | No | No |
The research gives no versions for the rows with "Yes". The tracker uses only the first three rows. It examines nothing else, thus it operates in each browser of the table.
What the tracker does in each engine
- Chromium sends all seven events. A page becomes
frozenatfreezeor at apagehidewithpersisted. - Firefox and Safari do not send
freezeandresume. There, a page becomesfrozenonly at apagehidewithpersistedset totrue. - All engines send
pageshowwithpersistedset totruefor a restore from the back/forward cache.
The listener order on window and on document
Experiment E1 measured the order of a bubble listener that the page added first and a capture listener that it added second:
| Target | Chromium 145 | Firefox 146 | WebKit (Safari 26.0 build) |
|---|---|---|---|
window, custom Event | Bubble first | Capture first | Capture first |
window, pagehide | Bubble first | Capture first | Capture first |
document, custom Event | Capture first | Capture first | Capture first |
document, Event with bubbles: true | Capture first | Capture first | Capture first |
document.body | Capture first | Capture first | Capture first |
On window, Chromium starts the listeners in the order of their registration. Capture phase and listener order tells what this means for an exporter, and how the export phase solves it.
Notes on the engines
- Before Safari 14 and 14.1,
visibilitychangedid not bubble towindow, and it did not occur when the user went to another page. The tracker listens forvisibilitychangeondocument, and it also usespagehide. - Chrome deprecated the
unloadevent in steps. From Chrome 154 (2026-09-22), Chrome does not startunloadlisteners. The tracker does not useunloadorbeforeunload. - Chrome freezes pages in the back/forward cache, in collapsed tab groups, and in hidden tabs that use much CPU time (Energy Saver, desktop, from Chrome 133, gradual rollout). On Android, it freezes background pages after 5 minutes, and after 1 minute from Chrome 139.
- A prerendered document is hidden until its activation.
- No web event tells a page that the operating system goes to sleep. A locked screen usually makes the page hidden, but not on each platform.
- A
visibility-stateentry withstartTime0 gives the first state of the page in Chromium. Thus a script that loads late can find out if the page was hidden before.
The focus of the document
The tracker uses document.hasFocus() to choose between active and passive. Without document.hasFocus(), for example in a simulated document, the tracker uses active for a visible page.
Sources
- Page Lifecycle, WICG draft, 2022-06-09.
- Chrome: Page Lifecycle API, the deprecation of the unload event, notRestoredReasons and Freezing on Energy Saver.
- ChromeStatus: the freeze of background pages on Android and the pause of workers on freeze.
- MDN: VisibilityStateEntry and Document.visibilityState.
- The lag project: browser support and local experiments, E1.