Skip to content

History API

This lesson explains History API with clear examples, use cases, and best practices so you can use HTML5 APIs confidently in real web applications.

HTML5 History API Overview

The HTML5 History API allows JavaScript to manipulate the browser's session history without performing a full page reload. It enables modern Single Page Applications (SPAs) to update the browser URL, store page state, and respond to Back and Forward navigation while keeping the user on the same page.

The History API is used by frameworks such as React Router, Angular Router, Vue Router, Next.js, Nuxt, and many custom routing libraries. It provides a smoother navigation experience while preserving browser history.

Feature Description
API Name History API
Main Object window.history
Main Event popstate
Main Purpose Modify browser history without page reload.
Used In SPA routing, dashboards, admin panels, navigation systems
Supported Browsers All modern browsers

History Object

The browser exposes the History API through the window.history object.

console.log(window.history);

The History object contains methods for navigating browser history, creating history entries, replacing entries, and determining the number of pages in the current session.

History API Methods

Method Description Example
back() Go back one page. history.back()
forward() Go forward one page. history.forward()
go() Move backward or forward multiple entries. history.go(-2)
pushState() Add a new history entry. history.pushState(...)
replaceState() Replace the current history entry. history.replaceState(...)

History Properties

Property Description
history.length Number of entries in the current session history.
history.state Returns the state object for the current history entry.

pushState()

The pushState() method creates a new history entry without reloading the page.

history.pushState(
  {
    page: "products"
  },
  "",
  "/products"
);

console.log(location.pathname);

The browser URL changes to /products, but the current page remains loaded.

replaceState()

The replaceState() method updates the current history entry instead of creating a new one.

history.replaceState(
  {
    page: "dashboard"
  },
  "",
  "/dashboard"
);

Unlike pushState(), this does not add another browser history entry.

Working with State Objects

history.pushState(
  {
    id: 105,
    category: "Books"
  },
  "",
  "/products/books"
);

console.log(history.state);

The first parameter is any serializable JavaScript object that you want associated with the history entry.

Handling Back and Forward Navigation

window.addEventListener(
  "popstate",
  (event) => {

    console.log(
      event.state
    );

    if (event.state) {

      console.log(
        event.state.page
      );

    }

  }
);

The popstate event fires whenever the active history entry changes because the user clicks the browser's Back or Forward button or when JavaScript calls history.go().

Navigate Browser History

// Go back

history.back();

// Go forward

history.forward();

// Go back two pages

history.go(-2);

// Go forward one page

history.go(1);

These methods behave similarly to clicking the browser's Back and Forward buttons.

Simple SPA Router Example

function navigate(path) {

  history.pushState(
    {
      path
    },
    "",
    path
  );

  render(path);

}

function render(path) {

  console.log(
    "Rendering:",
    path
  );

}

window.addEventListener(
  "popstate",
  () => {

    render(location.pathname);

  }
);

This demonstrates how many client-side routers work by updating the URL and rendering different views without reloading the page.

History Length

console.log(
  history.length
);

The length property returns the total number of entries in the current browser session history.

Feature Detection

if (
  "pushState" in history
) {

  console.log(
    "History API supported."
  );

} else {

  console.log(
    "History API unavailable."
  );

}

Always verify support before using advanced History API features in applications that target older browsers.

History API vs Location API

Feature History API Location API
Change URL ✔ Yes ✔ Yes
Reload Page ✘ No ✔ Usually
SPA Navigation ✔ Yes ✘ No
Browser History ✔ Yes Limited
Back Button Support ✔ Yes Native navigation only

Common History API Use Cases

Application Purpose
Single Page Applications Client-side routing.
Admin Dashboards Navigation without reloads.
E-commerce Sites Product filtering and navigation.
Documentation Websites Fast page transitions.
Online Editors Maintain editing state.
Maps Update URLs while navigating.
Search Applications Bookmark search results.
Progressive Web Apps Offline-friendly navigation.

History API Best Practices

  • Use pushState() only for meaningful navigation.
  • Use replaceState() for updating the current page.
  • Always listen for the popstate event.
  • Keep state objects small and serializable.
  • Update the page content after changing the URL.
  • Support browser refreshes on bookmarked URLs.
  • Use accessible navigation and meaningful URLs.
  • Implement server-side routing support for SPA URLs.

Common History API Mistakes

  • Calling pushState() without updating page content.
  • Ignoring the popstate event.
  • Storing very large objects in history state.
  • Creating unnecessary history entries.
  • Using the History API for external navigation.
  • Breaking browser Back button behavior.
  • Forgetting server-side support for SPA routes.
  • Assuming every browser behaves exactly the same.

Key Takeaways

  • The History API updates browser history without reloading pages.
  • Use pushState() to create new history entries.
  • Use replaceState() to modify the current entry.
  • Handle browser navigation with the popstate event.
  • The History API is the foundation of modern SPA routing.
  • Always keep URLs meaningful and bookmark-friendly.

Pro Tip

Modern frameworks such as React Router, Vue Router, Angular Router, Next.js, Nuxt, Remix, and SvelteKit are built on top of the History API. Understanding pushState(), replaceState(), and popstate makes it much easier to understand how client-side routing works internally.