The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Read the URL property on the browser object you already use: Selenium exposes driver.current_url, while Playwright exposes page.url. Both return a Python string, and neither accessor takes parentheses.
# Selenium
print(driver.current_url)
# Playwright
print(page.url)
The value belongs to the active browsing context (Selenium) or the specific Playwright Page object (tab or popup). After an action that navigates, synchronize with that navigation before reading the value your next step depends on.
The two Python accessors at a glance
| Framework | Accessor | What it represents | Async syntax |
|---|---|---|---|
| Selenium | driver.current_url |
The current URL in WebDriver’s current browsing context | The property read itself is ordinary Python access |
| Playwright | page.url |
The URL of one Playwright Page, which is a tab or popup |
Await browser and navigation operations; read page.url directly |
These are properties, not methods. Writing driver.current_url() or page.url() attempts to call the returned string and raises a TypeError.
Get the current URL with Selenium
Complete synchronous example
Create a WebDriver, navigate with get(), read current_url, and close the browser in a finally block so cleanup still runs if navigation or your assertion fails.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
from selenium import webdriver
driver = webdriver.Chrome()
try:
driver.get("https://example.com")
current = driver.current_url
print(current)
finally:
driver.quit()
driver.current_url is a string snapshot. Store it when you need to compare the address before and after a click, submit it to a logger, or pass it to another Python function.
Use it in an assertion
from selenium import webdriver
driver = webdriver.Chrome()
try:
driver.get("https://example.com/login")
driver.find_element("css selector", "button[type='submit']").click()
actual_url = driver.current_url
if "/dashboard" not in actual_url:
raise AssertionError(f"Unexpected destination: {actual_url}")
finally:
driver.quit()
The click must have completed the navigation you are testing before you consume current_url. Use Selenium’s normal explicit wait strategy for the page state your test requires rather than adding an arbitrary sleep.
Get the current URL with Playwright
Synchronous Playwright
In the synchronous API, read page.url after creating a page and navigating it.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com")
print(page.url)
browser.close()
A Playwright browser context can contain several pages. The variable named page determines which tab’s URL you receive; reading another Page object reads another tab.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Asynchronous Playwright
In async code, await browser and page operations, but do not await the URL property itself.
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto("https://example.com")
print(page.url)
await browser.close()
asyncio.run(main())
await page.url is incorrect because page.url is already a string. Await the operation that changes the page, then read the property.
Rank #2
Synchronize after navigation before reading
A browser can update the address when navigation is committed while still loading resources and rendering the document. If the next line depends on the destination, coordinate the action and navigation instead of reading immediately after a click.
Playwright: wait for the expected URL
Use page.wait_for_url() with a URL or pattern that describes the destination. Then read page.url.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/start")
page.get_by_role("link", name="Continue").click()
page.wait_for_url("**/complete")
print(page.url)
browser.close()
For an async page, use await page.wait_for_url(...) and then read page.url without await. Choose a pattern that matches the redirect and query-string behavior of your application.
Selenium: wait for the condition your test needs
Selenium’s accessor has no separate URL-wait method requirement: perform an explicit wait for the expected URL or page condition, then read driver.current_url. This keeps the wait tied to an observable result instead of a fixed delay.
Reading URLs when tabs and popups are involved
Selenium browsing contexts
driver.current_url follows whichever window handle WebDriver has selected. If your code opens a new tab, switch to that window before reading the URL; otherwise you will read the original tab’s address.
handles_before = set(driver.window_handles)
# Trigger the link or action that opens a tab here.
new_handle = (set(driver.window_handles) - handles_before).pop()
driver.switch_to.window(new_handle)
print(driver.current_url)
The example assumes your code has already waited until the second handle exists. Keep the handle associated with each tab if later steps must return to the original page.
Rank #3
Playwright pages and popups
Each Playwright Page has its own URL. Capture the new page object when the popup opens, then read that object’s property.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context()
page = context.new_page()
page.goto("https://example.com")
with context.expect_page() as popup_info:
page.get_by_role("link", name="Open report").click()
popup = popup_info.value
popup.wait_for_load_state()
print(popup.url)
browser.close()
Reading page.url after this action would still refer to the opener, not the popup.
Common mistakes and fixes
Calling the property like a function
Symptom: TypeError: 'str' object is not callable.
Cause: Parentheses were added to a property.
Fix: Use driver.current_url or page.url, never driver.current_url() or page.url().
Reading too early after a click
Symptom: The value is the old address, an intermediate redirect, or a URL that does not satisfy the assertion.
Recommended Free Tools
Cause: The navigation has not reached the state your test expects. URL commitment and complete loading are separate events.
Fix: In Playwright, wait with page.wait_for_url(). In Selenium, explicitly wait for the expected URL or a page condition, then read the property.
Rank #4
Inspecting the wrong tab
Symptom: The URL is valid but belongs to the opener or another tab.
Cause: Selenium is still on the old window handle, or your Playwright code is reading a different Page object.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Fix: Switch Selenium to the new handle, or retain and inspect the Playwright page returned for the popup.
Seeing about:blank or an initial URL
Symptom: A newly created page reports about:blank.
Cause: No navigation has been issued yet, or the popup object was captured before its navigation began.
Fix: Navigate the page and synchronize with the popup or destination before reading its URL.
Using the wrong object in async Playwright
Symptom: An error appears when awaiting page.url, or code treats it as a coroutine.
Best Value
Cause: Only Playwright operations such as goto() and wait_for_url() are awaited; page.url is a regular string property.
Fix: Await the navigation operation, then assign current = page.url.
Reliability and performance considerations
- The property lookup itself is inexpensive; browser startup, navigation, redirects, and waits account for nearly all elapsed time in a URL-checking script.
- Use one browser session for multiple related checks when isolation is not required. Recreating a browser for every URL adds startup overhead.
- Use explicit, condition-based waits so a fast page is not delayed by a long fixed sleep, while a slower redirect is not read prematurely.
- Record the URL at the point where it matters. A later navigation can change the same tab’s value, so do not assume a previously read string updates automatically.
- When a test fails, log the observed URL and the expected pattern. This distinguishes a genuine application redirect from a synchronization or tab-selection bug.
Or skip the browser setup
If your goal is a rendered image or PDF rather than a Python string containing the current URL, ScreenshotNeo provides a single-request screenshot API. It accepts consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; 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 billing status.
The API also offers an MCP server for Claude, Cursor, and other MCP clients, with take_screenshot, get_page_info, and capture_pdf tools. Features include full-page captures with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS or JavaScript, clicks before capture, selector hiding, selector/delay/network-idle waits, request and resource blocking, custom headers/cookies/user agents, Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Common parameter names used by other screenshot APIs are accepted to ease migration.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11One-call examples
See the ScreenshotNeo documentation for the complete option list. The basic Python request is:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Equivalent cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Equivalent 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}`);
Plans and billing
| Plan | Monthly allowance | Price |
|---|---|---|
| Free | 1,000 shots | $0, no card |
| Starter | 3,000 shots | $5 |
| Growth | 15,000 shots | $15 |
| Pro | 60,000 shots | $39 |
| Scale | 250,000 shots | $99 |
| Business | 1,000,000 shots | $249 |
Every feature is available on every plan, and yearly billing gives two months free. This service does not replace driver.current_url or page.url when your program needs the address string; it is an option when the deliverable is a clean screenshot, PDF, or agent-accessible page information.
Sign up for the free plan to get 1,000 screenshots a month with no card, or move to paid usage starting at $5 for 3,000 shots.
Frequently Asked Questions
What if I only have a URL string and no browser object?
A URL string has no current browsing context to inspect. Selenium’s and Playwright’s accessors read the address held by an active WebDriver or Page; if you only need to manipulate a known string, use normal Python string or URL-parsing code instead of a browser accessor.
Can ScreenshotNeo return the URL string that Selenium or Playwright exposes?
No. ScreenshotNeo is intended for captures, PDFs, and page-information workflows. Use driver.current_url or page.url when your program specifically needs the browser’s current address.
Quick Recap
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.

