Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read window.location.href. It returns the complete URL of the page currently open, including its protocol, host, path, query string, and fragment.

const currentUrl = window.location.href;
console.log(currentUrl);

Get the complete current URL

window.location is a Location object for the current document. Its href property is the full URL as a string. The equivalent document.location.href expression reads the same document location.

function readCurrentUrl() {
  return window.location.href;
}

const url = readCurrentUrl();
console.log(url);

For a page loaded at https://example.com/products?category=books#reviews, href contains that entire value. Reading it does not make a network request or navigate away from the page.

Read only the URL component you need

Use the specific Location property when the full URL would be unnecessary or unsafe to pass around.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Property Value for https://shop.example:8443/items?sort=price#sale Use it for
href https://shop.example:8443/items?sort=price#sale The complete URL
origin https://shop.example:8443 Protocol, hostname, and port together
host shop.example:8443 Hostname plus an optional port
pathname /items The path, without query or fragment
search ?sort=price The query string, including its leading question mark
hash #sale The fragment, including its leading hash sign

These values are read directly from the same Location object:

const { href, origin, host, pathname, search, hash } = window.location;

console.log({ href, origin, host, pathname, search, hash });

Do not use pathname when you need campaign parameters, and do not treat search as a complete URL. The component properties intentionally exclude the other portions.

Get query parameters with URL and URLSearchParams

For structured access to query parameters, parse the current URL with the URL constructor and use its searchParams property.

const current = new URL(window.location.href);
const campaign = current.searchParams.get('campaign');

console.log(campaign);

get() returns the parameter value, or null when that name is absent. It also decodes percent-encoded text for you. Use has() when you only need a Boolean, and getAll() when a parameter can occur more than once.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const params = new URL(window.location.href).searchParams;

if (params.has('filter')) {
  console.log('A filter was supplied');
}

const tags = params.getAll('tag');
console.log(tags);

For a URL such as https://example.com/search?q=browser%20url&tag=js&tag=web, get('q') produces browser url, while getAll('tag') produces both tag values. If your application accepts user-controlled parameters, validate the returned values before using them in HTML, redirects, database queries, or authorization decisions.

Build a small helper for reusable URL data

Keeping URL parsing in one function prevents each component from handling query strings and fragments differently.

function getCurrentUrlData() {
  const url = new URL(window.location.href);

  return {
    href: url.href,
    origin: url.origin,
    host: url.host,
    pathname: url.pathname,
    search: url.search,
    hash: url.hash,
    params: url.searchParams
  };
}

const page = getCurrentUrlData();
console.log(page.pathname);
console.log(page.params.get('page'));

Return the URL object itself when callers need methods such as URLSearchParams.set() or URLSearchParams.delete(). Remember that changing that object does not change the browser address bar until you assign a resulting string to a navigation API.

Read the URL at the right time

Initial page load

Inline scripts and scripts loaded with a normal page can read window.location.href as soon as the document has a browsing context. You do not need to wait for images or other page resources just to read the URL.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Single-page applications

Read the location again whenever your application handles navigation. A router may update the address with the History API without performing a full reload, so code that captured the value once at startup can become stale. Have the router call your URL-reading function after its route change, and handle popstate if your code owns history navigation.

function reportRoute() {
  const url = new URL(window.location.href);
  console.log(url.pathname, url.searchParams.get('tab'));
}

window.addEventListener('popstate', reportRoute);
window.addEventListener('hashchange', reportRoute);
reportRoute();

The hashchange event is useful when a user changes only the fragment. A history update made with pushState() does not automatically fire popstate at the moment of the call, so call your route handler explicitly after such an update.

Read a URL from an iframe

Scripts can inspect an iframe’s document location only when the parent and iframe satisfy the browser’s same-origin policy. “Same origin” means the scheme, hostname, and port all match. A cross-origin frame’s complete Location.href is not readable by the parent; cross-origin location access is restricted to protect the framed site.

When you control both documents but they are on different origins, exchange the value with window.postMessage(). Validate the sender’s origin rather than accepting arbitrary messages.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
// Code running inside the iframe
window.parent.postMessage(
  { type: 'current-url', href: window.location.href },
  'https://app.example'
);
// Code running in the parent page
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://widget.example') return;
  if (!event.data || event.data.type !== 'current-url') return;

  console.log(event.data.href);
});

Replace both example origins with the exact origins you trust. If the frame is untrusted, do not forward sensitive URL data to it.

Reading is different from navigating

Accessing location.href is a read. Assigning to it is a navigation:

const destination = 'https://example.com/account';
window.location.href = destination;

window.location.assign(destination) has the same history behavior: the new page is added to the session history, so Back can return to the current page. window.location.replace(destination) navigates without keeping the current page as a separate history entry.

window.location.assign('/next-step');
// The user can normally go Back to this page.

window.location.replace('/signed-out');
// This page is replaced in the session history.

Never assign unvalidated user input to a location property. A redirect target should be checked against the destinations your application actually permits.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common mistakes and fixes

Only the path appears

Symptom: You log /docs but expected the query string.

Cause: pathname excludes both search and hash.

Fix: Use href for the complete value, or read search and hash separately.

The question mark or hash is missing

Symptom: Your parser receives page=2 instead of ?page=2, or section instead of #section.

Cause: You selected a value that intentionally omits its delimiter, or removed it during string processing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fix: Use location.search and location.hash when you need the delimiters, or use URLSearchParams when you need parameter values rather than the raw query string.

A parameter is unexpectedly null

Symptom: searchParams.get('id') returns null.

Cause: The parameter name is absent, misspelled, or differs in case. Parameter names are case-sensitive.

Fix: Check has(), inspect search, and account for the missing-value path before converting or displaying the result.

The URL works in the browser but not in server-side code

Symptom: Node.js or server-rendered code throws “window is not defined.”

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Cause: A server process has no browser window or current tab.

Fix: Pass the request URL into the server function explicitly, or run the location-reading code only in the browser. Do not pretend that a server has one universal “current browser URL” when several users may be connected.

An iframe URL cannot be read

Symptom: Access to a frame’s location throws a security exception or exposes no readable URL.

Cause: The frame is cross-origin.

Fix: Use a same-origin deployment, or implement a postMessage protocol with strict origin checks in both documents.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Examples with one URL

Suppose the browser address is https://news.example:443/story/42?ref=email&ref=home#comments. The corresponding values are:

Expression Result
location.href https://news.example:443/story/42?ref=email&ref=home#comments
location.origin https://news.example:443
location.pathname /story/42
location.search ?ref=email&ref=home
location.hash #comments
new URL(location.href).searchParams.getAll('ref') ['email', 'home']

Or skip the browser setup

If your goal is to obtain a clean image or PDF of a URL rather than inspect the URL inside your own page, ScreenshotNeo provides a website screenshot API and MCP server. It accepts a URL in one request and returns PNG, JPEG, WebP, or PDF output.

For a direct request, see the ScreenshotNeo API documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same call from Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

And from Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));

ScreenshotNeo can accept consent banners before capture and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and whether the request was billed. It also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to try it without a card.

Performance, reliability, and privacy notes

  • Reading a Location property is synchronous and local; it does not wait for the network.
  • Constructing new URL(window.location.href) gives you validated, structured fields instead of manual string splitting.
  • Do not log complete URLs by default. Query strings and fragments can contain email addresses, tokens, search terms, or other sensitive data.
  • Use the smallest value required by the next function. Passing pathname instead of the complete URL reduces accidental leakage of query data.
  • When navigation can happen without a reload, keep one route-change path responsible for refreshing derived URL state.

Frequently Asked Questions

Can JavaScript read the URL before the page finishes loading?

Yes. The current document location is available as soon as the page has a browsing context; waiting for images or other resources is not required just to read it.

What should a server-rendered application use instead of window.location?

Use the URL supplied with the incoming HTTP request and pass the relevant value into browser code. A server process has no single browser window to inspect.

Can I safely put the current URL into an analytics event?

Only after deciding which components are appropriate. Query strings and fragments may contain personal or secret data, so remove or redact sensitive values before logging or sending them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.