Question

How to Modify the URL Without Reloading the Page in JavaScript

htmljavascripturlurl-rewritingfriendly-url

Question

I want to change the URL of the current page in JavaScript without causing the browser to reload the page.

For example, assigning a new value to window.location.href reloads the page:

window.location.href = "www.mysite.com/page2.php";

Is there a way to update only the path or other parts of the current URL after the domain without reloading?

If possible, I would also like to access or modify the part of the URL before the # hash.

Short Answer

By the end of this page, you will understand how JavaScript can update the browser URL without refreshing the page, when to use the History API versus the hash portion of the URL, and what restrictions apply when changing paths, query strings, and fragments.

Concept

The core concept behind this question is client-side URL manipulation.

Normally, when you assign a new value to window.location.href, the browser treats it as a navigation request. That means it loads a new page from the server.

However, modern browsers also provide the History API, which lets JavaScript update the URL shown in the address bar without reloading the page.

The two main methods are:

history.pushState(state, title, url)
history.replaceState(state, title, url)

These methods are useful in single-page applications, filters, tabs, dashboards, and search pages where the UI changes but a full page reload would be unnecessary.

Why this matters

Changing the URL without reloading is important because:

  • users can bookmark the current app state
  • the back and forward buttons can still work
  • URLs can reflect selected filters, tabs, or views
  • the page feels faster because it avoids full reloads

What you can change

You can update:

  • the path, such as /page2
  • the query string, such as ?sort=price
  • the hash, such as #section3

But there is an important rule:

  • you can only use the History API for URLs on the same origin
  • same origin means same protocol, host, and port

So this is allowed if you stay on the same site:

history.pushState({}, "", "/page2.php")

But changing to a different domain is not allowed with pushState.

Accessing the part before the hash

Yes, you can access the part before #.

For example:

const fullUrl = window.location.href;
const beforeHash = fullUrl.split("#")[0];
console.log(beforeHash);

You can also use the more reliable location parts:

console.log(location.origin);   // domain
console.log(location.pathname); // path
console.log(location.search);   // query string
console.log(location.hash);     // hash

In real programming, developers usually avoid manually splitting URLs when built-in properties already provide the exact parts they need.

Mental Model

Think of the browser URL like a label on a folder.

  • window.location.href = ... is like throwing away the current folder and opening a different one.
  • history.pushState(...) is like changing the label on the folder while keeping the contents currently open.
  • changing location.hash is like adding a sticky note to the folder label.

The page reload happens when the browser thinks you are requesting a new document. The History API avoids that by changing the address bar and browser history without making the browser load a new page.

Take Quiz

Syntax and Examples

Core syntax

history.pushState(stateObject, "", newUrl);
history.replaceState(stateObject, "", newUrl);
  • pushState adds a new history entry
  • replaceState updates the current history entry
  • the second argument is traditionally unused in modern code, so an empty string is common

Example: change the path without reload

history.pushState({}, "", "/page2.php");

This updates the URL in the address bar to /page2.php on the current domain without reloading the page.

Example: change the query string

history.pushState({}, "", "/products?category=books");

This is useful for filters or search pages.

Example: replace instead of push

history.replaceState({}, "", "/profile?tab=settings");

This changes the current URL but does not add a new browser history entry.

Example: change only the hash

location.hash = "section2";

This usually does not reload the page. It updates only the fragment portion of the URL.

Reading the URL parts

console.log(location.href);      // full URL
console.log(location.origin);    // https://example.com
console.log(location.pathname);  // /page2.php
console.log(location.search);    // ?category=books
console.log(location.hash);      // #section2

Beginner-friendly example

function showSettingsTab() {
  document.body.textContent = "Settings tab is open";
  history.pushState({}, "", "/account?tab=settings");
}

showSettingsTab();

What this does

  • changes the page content
  • updates the URL to match that content
  • does not refresh the browser page

Step by Step Execution

Consider this code:

console.log(location.pathname);
history.pushState({}, "", "/dashboard?view=weekly#chart");
console.log(location.pathname);
console.log(location.search);
console.log(location.hash);

Step by step

  1. The first console.log(location.pathname) prints the current path.
  2. history.pushState({}, "", "/dashboard?view=weekly#chart") changes the browser URL without reloading.
  3. The next console.log(location.pathname) now prints /dashboard.
  4. console.log(location.search) prints ?view=weekly.
  5. console.log(location.hash) prints #chart.

Important detail

The JavaScript environment continues running on the same page. No new document is loaded.

Example trace

If the original URL is:

https://example.com/home

After pushState, the browser shows:

https://example.com/dashboard?view=weekly#chart

But the page was not reloaded. Only the visible URL and history entry changed.

Real World Use Cases

Changing the URL without reloading is common in many types of applications.

Single-page applications

Frameworks like React, Vue, and Angular use this approach for client-side routing.

Example:

  • /dashboard
  • /dashboard/reports
  • /dashboard/settings

The app changes views without a full page refresh.

Filtered product pages

An online store may update the URL when a user selects filters:

/products?category=shoes&color=black

This makes the filtered view shareable and bookmarkable.

Tabs and panels

A profile page might update the URL when the user opens a tab:

/profile?tab=security

Search interfaces

A search tool might store the current search term or sort order in the URL.

Documentation pages

A docs site may use hashes for section navigation:

/docs/api#authentication

Maps and dashboards

Applications often store zoom level, selected date range, or current panel in the URL so the state can be restored later.

Take Quiz

Real Codebase Usage

In real projects, developers usually combine URL updates with application state.

Common pattern: update UI and URL together

function setView(view) {
  renderView(view);
  history.pushState({ view }, "", `/dashboard?view=${view}`);
}

This keeps the browser URL consistent with what the user sees.

Guard clause for invalid input

function setTab(tab) {
  const allowedTabs = ["profile", "security", "billing"];

  if (!allowedTabs.includes(tab)) {
    return;
  }

  history.replaceState({ tab }, "", `/account?tab=${tab}`);
}

This prevents invalid URLs from being generated.

Reading URL parameters on load

const params = new URLSearchParams(location.search);
const tab = params.get("tab") || "profile";
renderTab(tab);

This lets the app restore state from the URL.

Handling back and forward navigation

When using pushState, applications often listen for popstate:

window.addEventListener("popstate", (event) => {
  console.log("History changed:", event.state);
  renderFromUrl();
});

This is important because users expect the browser's back button to work.

When replaceState is preferred

Developers often use replaceState when:

  • correcting the current URL
  • normalizing query parameters
  • updating temporary state that should not create extra history entries

Common Mistakes

1. Using window.location.href when you do not want navigation

Broken example:

window.location.href = "/page2.php";

This reloads the page.

Use this instead:

history.pushState({}, "", "/page2.php");

2. Trying to change to another domain

Broken example:

history.pushState({}, "", "https://othersite.com/page");

This will fail because the History API only works with the same origin.

3. Updating the URL but not updating the UI

Broken example:

history.pushState({}, "", "/settings");

If you change the URL but leave the page content unchanged, users may be confused.

Better:

renderSettingsPage();
history.pushState({}, "", "/settings");

4. Using string splitting when built-in URL properties exist

Less reliable:

const beforeHash = location.href.split("#")[0];

Usually better:

const base = location.origin + location.pathname + location.search;

5. Forgetting back-button behavior

If you use pushState many times but never handle popstate, the user may go back to a URL that does not match the visible UI.

6. Confusing hash changes with path changes

location.hash = "about";

This changes only the fragment. It does not change the actual path like /about.

7. Omitting the leading slash in relative paths

Potentially confusing:

history.pushState({}, "", "page2.php");

Clearer:

history.pushState({}, "", "/page2.php");

Using a leading slash makes it obvious that the path is relative to the site root.

Comparisons

ApproachReloads page?Changes history?Best use case
window.location.href = ...YesYesNavigate to a new page or resource
location.assign(...)YesYesSame as href, explicit navigation
location.replace(...)YesReplaces current entryRedirect without keeping old page in history
history.pushState(...)NoYesUpdate path/query/hash in SPA-style navigation
history.replaceState(...)NoReplaces current entryUpdate current URL without adding a new history entry
location.hash = ...Usually noYesJump to or store fragment/section state

pushState vs replaceState

MethodAdds new history entry?Back button returns to previous URL?
pushStateYesYes
replaceStateNoNo, current entry is overwritten

Hash routing vs History API

TechniqueExample URLLooks cleaner?Server configuration needed?
Hash routing/app#settingsNoUsually no
History API routing/app/settingsYesOften yes

The History API usually gives cleaner URLs, but hash-based URLs are simpler in some static setups.

Take Quiz

Cheat Sheet

// Reloads page
window.location.href = "/page2.php";

// Change URL without reload
history.pushState({}, "", "/page2.php");

// Change current history entry without reload
history.replaceState({}, "", "/page2.php");

// Change only the hash
location.hash = "section1";

// Read URL parts
location.href      // full URL
location.origin    // protocol + domain + port
location.pathname  // path
location.search    // query string
location.hash      // fragment

Rules

  • window.location.href = ... navigates and reloads
  • history.pushState() does not reload
  • history.replaceState() does not reload and does not add a new history entry
  • History API works only on the same origin
  • use popstate to respond to back/forward navigation

Quick tip

To get everything before the hash:

const beforeHash = location.origin + location.pathname + location.search;

Or:

const beforeHash = location.href.split("#")[0];

FAQ

Can I change the URL path without refreshing the page in JavaScript?

Yes. Use history.pushState() or history.replaceState() to update the URL without reloading.

Does window.location.href always reload the page?

Yes. Setting window.location.href triggers navigation, so the browser loads the target URL.

What is the difference between pushState and replaceState?

pushState adds a new history entry. replaceState modifies the current history entry.

Can I modify only the hash without reloading?

Yes. You can set location.hash = "section1". This usually does not reload the page.

Can I change the URL to another domain without reloading?

No. The History API only allows same-origin URLs.

How do I get the URL without the hash part?

You can use:

const beforeHash = location.origin + location.pathname + location.search;

Why does my URL change but my page content stay the same?

Because pushState changes the address bar only. You must also update the UI yourself.

Do browsers support the History API?

Yes, modern browsers support it. It is widely used in single-page applications.

Take Quiz

Mini Project

Description

Build a small profile page view switcher that changes the URL when a user selects a tab, without reloading the page. This demonstrates how real applications keep the URL in sync with what the user sees.

Goal

Create a tab-based interface that updates the page content and browser URL using the History API.

Requirements

  • Create three tabs: Profile, Security, and Billing.
  • When a tab is selected, update the visible content without reloading the page.
  • Update the URL query string to reflect the selected tab.
  • Restore the correct tab when the page loads from the current URL.
  • Handle the browser back and forward buttons correctly.
Take Quiz

Keep learning

Related questions

View more