Get and assert the current URL in Playwright
Read page.url() synchronously, use retrying URL assertions, and handle query parameters, frames, and popups.
page.url() synchronously returns the current main-frame URL. You do not need await. To verify a navigation outcome, use await expect(page).toHaveURL(...), which retries until the URL matches. A matching URL does not, by itself, prove that the destination's application data has loaded.
Read the current URL
const { test, expect } = require('@playwright/test');
test('URL after login', async ({ page }) => {
await page.goto('https://example.com/login');
// Perform your application's login steps here.
console.log(page.url());
});
Replace the example URL and login steps with your application's flow. The returned string is a snapshot taken at that moment.
Assert a navigation outcome
// Exact URL.
await expect(page).toHaveURL('https://example.com/dashboard');
// Match a path while allowing additional URL content.
await expect(page).toHaveURL(/\/dashboard/);
// A dynamic path segment. String arguments are not glob patterns.
await expect(page).toHaveURL(/\/user\/[^/]+\/profile(?:[?#].*)?$/);
If you read page.url() before the URL changes, you get the previous address. A retrying assertion expresses the expected destination without relying on that timing. Choose a pattern narrow enough to exclude unintended destinations.
Parse query parameters
const url = new URL(page.url());
console.log(url.pathname); // For example, /dashboard.
console.log(url.searchParams.get('tab')); // settings for ?tab=settings.
Wait for a URL before reading it
await page.getByRole('link', { name: 'Docs' }).click();
await page.waitForURL(/\/docs/);
console.log(page.url());
Wait separately for the application's readiness condition when URL matching is insufficient, such as a dashboard populated by a later API request.
Frequently asked questions
How do I get an iframe's URL?
page.url() refers to the main frame. Use page.frameLocator('#iframe-id') to locate elements inside an iframe. To read the frame's URL, find the corresponding Frame through methods such as page.frames() and call frame.url().
Do hash-based SPA routes work?
Yes. The fragment is part of the URL, so toHaveURL(/#\/users/) can match it. waitForURL() also handles hash changes without requiring a new document to load.
What about a new tab or popup?
Listen for context.on('page') or register page.waitForEvent('popup') before the triggering action. Each resulting Page has its own .url(); reading one does not read the other.
References
Related reading
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan