ScreenshotNeo

BlogHow-to

How to Use getAttribute() in Selenium

Use getAttribute() on a located WebElement to read a value. Learn when it returns a live property, when to use DOM-specific methods, and how each Selenium binding behaves.

By the ScreenshotNeo team4 October 20269 min read

Locate the element, then call getAttribute("name") in Java or JavaScript, or get_attribute("name") in Python. The method is a convenience lookup: it may return a live DOM property before falling back to the HTML attribute. If you need to know exactly what was declared in markup or what the element’s current state is, use the binding’s DOM-attribute or DOM-property method instead.

from selenium.webdriver.common.by import By

link = driver.find_element(By.CSS_SELECTOR, "a.next")
href = link.get_attribute("href")

For example, an input’s value attribute may represent its initial markup value, while its value property reflects a value entered later. Selenium’s property-first behavior can therefore produce a value that differs from the original HTML. See the official Selenium documentation for element information and the binding-specific Python, Java, and JavaScript APIs.

Choose the right retrieval method

Decide what you are asserting before choosing a method. Selenium documents getAttribute as a property-first lookup in the cited bindings; DOM-specific methods make the intended source explicit.

What you need Python Java JavaScript
Convenience lookup: property first, then attribute get_attribute(name) getAttribute(name) getAttribute(name)
Attribute declared in the element’s markup get_dom_attribute(name) getDomAttribute(name) getDomAttribute(name)
Current DOM property get_property(name) getDomProperty(name) getProperty(name)

Use the DOM attribute method to check a declared attribute, such as href as written in markup. Use the property method for live state, such as an input’s current value after typing. Use getAttribute when its property-first fallback is what you want. These methods inspect the live DOM; they do not retrieve the original HTTP response source after the page or scripts have changed the document.

Python: runnable example

Install Selenium with python -m pip install selenium. This script opens a data URL, reads a link’s attribute and property, and quits the browser. Selenium Manager can obtain and manage a compatible browser driver for supported setups; Chrome must be installed.

from selenium import webdriver
from selenium.webdriver.common.by import By

html = """<!doctype html>
<a id='next' href='/first'>Next</a>
<input id='email' value='initial@example.test'>
<script>
  document.querySelector('#email').value = 'current@example.test';
</script>
"""

driver = webdriver.Chrome()
try:
    driver.get("data:text/html;charset=utf-8," + html)

    link = driver.find_element(By.ID, "next")
    print("href convenience:", link.get_attribute("href"))
    print("href markup:", link.get_dom_attribute("href"))

    email = driver.find_element(By.ID, "email")
    print("value convenience:", email.get_attribute("value"))
    print("value markup:", email.get_dom_attribute("value"))
    print("value property:", email.get_property("value"))
finally:
    driver.quit()

For a production test, replace the data URL with your page and wait until the relevant element exists and its state is ready. Avoid assuming the output will always be a string: Python’s get_attribute may return a boolean for values Selenium considers truthy, and returns None when no matching property or attribute is set. The DOM-specific methods are preferable when you need to distinguish markup from live state.

Java: runnable example

Add Selenium Java to your project using the dependency instructions for your build tool in the official Selenium getting started guide. This example uses Selenium Manager through new ChromeDriver(); install Chrome first.

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class AttributeExample {
    public static void main(String[] args) {
        String html = "<!doctype html>"
            + "<a id='next' href='/first'>Next</a>"
            + "<input id='email' value='initial@example.test'>"
            + "<script>document.querySelector('#email').value = 'current@example.test';</script>";
        String dataUrl = "data:text/html;charset=utf-8," +
            URLEncoder.encode(html, StandardCharsets.UTF_8);

        WebDriver driver = new ChromeDriver();
        try {
            driver.get(dataUrl);
            WebElement link = driver.findElement(By.id("next"));
            System.out.println("href convenience: " + link.getAttribute("href"));
            System.out.println("href markup: " + link.getDomAttribute("href"));

            WebElement email = driver.findElement(By.id("email"));
            System.out.println("value convenience: " + email.getAttribute("value"));
            System.out.println("value markup: " + email.getDomAttribute("value"));
            System.out.println("value property: " + email.getDomProperty("value"));
        } finally {
            driver.quit();
        }
    }
}

Java’s API returns a nullable string for these methods. For a missing value, check for null before comparing or calling methods on the result.

JavaScript: runnable example

Install the Selenium JavaScript package with npm install selenium-webdriver, and ensure Chrome is installed. Selenium’s WebElement retrieval methods are asynchronous, so await them.

const { Builder, By } = require('selenium-webdriver');

(async function main() {
  const html = `<!doctype html>
    <a id="next" href="/first">Next</a>
    <input id="email" value="initial@example.test">
    <script>document.querySelector('#email').value = 'current@example.test';</script>`;
  const dataUrl = 'data:text/html;charset=utf-8,' + encodeURIComponent(html);
  const driver = await new Builder().forBrowser('chrome').build();

  try {
    await driver.get(dataUrl);
    const link = await driver.findElement(By.id('next'));
    console.log('href convenience:', await link.getAttribute('href'));
    console.log('href markup:', await link.getDomAttribute('href'));

    const email = await driver.findElement(By.id('email'));
    console.log('value convenience:', await email.getAttribute('value'));
    console.log('value markup:', await email.getDomAttribute('value'));
    console.log('value property:', await email.getProperty('value'));
  } finally {
    await driver.quit();
  }
})();

The JavaScript API documents getAttribute as resolving to a string or null; await it before inspecting the result. Do not copy return-type assumptions from another language binding.

What getAttribute returns

For a named value, Selenium’s convenience method checks the same-named DOM property and falls back to the attribute if the property is unavailable. If neither is set, the result is absent: Java and JavaScript use null; Python uses None for this case, though Python’s convenience method can also return booleans.

  • Relative URLs: an anchor’s href property commonly resolves to an absolute URL, while its markup attribute can remain relative. Read the DOM attribute when you need the literal declared path; read the property when you need the browser-resolved value.
  • Form values: an input’s value property can change after typing or script execution. The value attribute generally concerns the declared/default value. Choose based on whether the test checks initial markup or current form state.
  • Boolean attributes: attributes such as disabled, checked, selected, and required have presence-oriented HTML semantics. The Java documentation describes boolean attributes as returning "true" when present and null when absent for its attribute methods. Python and JavaScript details differ; consult the binding API and prefer an explicit DOM method when the distinction matters. For current checkbox or option selection, Selenium also provides is_selected() in Python, isSelected() in Java, and isSelected() in JavaScript.
  • Special names: Java’s getAttribute handles the common names class and readonly by consulting className and readOnly properties. Avoid assuming all bindings normalize names identically.
  • Missing values: check for null/None before using the returned value. A missing result is not the same as an empty string.

Reliable lookup and assertions

  1. Use a stable locator. Prefer an ID, a meaningful CSS selector, or another locator tied to the page’s structure over brittle positional selectors.
  2. Wait for the relevant state. Finding an element does not guarantee an asynchronous script has finished updating its property. Use an explicit wait for the condition your test needs.
  3. Read once and assert the intended source. For markup, use the DOM attribute method. For a live value, use the property method. This makes the assertion’s meaning clear.
  4. Re-find elements after navigation or rerender. A stored WebElement can become stale if its node is replaced. Locate it again after the page changes.
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

field = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "email"))
)
current_value = field.get_property("value")
assert current_value == "person@example.test"

The example waits for presence, not for the value itself. If a script populates the field later, wait for the desired property value with a condition tailored to the page before asserting.

Common errors and fixes

Symptom Likely cause Fix
NoSuchElementException or NoSuchElementError The locator matches nothing in the current page or browsing context, or the element has not appeared yet. Check the selector against the live DOM, wait for the element, and switch to the correct frame or window if applicable.
Value differs from page source getAttribute returned a live property, a resolved URL, or a value updated by script. Use get_dom_attribute/getDomAttribute for the declared attribute, or the property method for current state.
Result is None or null Neither matching property nor attribute is set, or the name is wrong. Verify the exact attribute/property name and that the located node is the expected element; handle missing values explicitly.
StaleElementReferenceException The node was detached or replaced after it was located. Wait for the update to finish and locate the element again before reading its value.
Python comparison fails despite a seemingly correct result get_attribute may return a boolean for values Selenium considers truthy, rather than a string. Inspect the actual type; use a DOM-specific method for an attribute string or assert the boolean meaning explicitly.
JavaScript code sees a Promise instead of a value The asynchronous WebElement method was not awaited. Use await element.getAttribute("name") inside an async function.
Value is outdated or intermittently empty The page is still loading or a client-side update has not completed. Wait for the expected value or page condition, not an arbitrary long sleep.

Performance, reliability, and cost

Attribute/property reads are small WebDriver commands, but remote browser sessions still require communication between your test code and the browser. Keep lookups targeted, avoid repeatedly fetching the same value in a loop, and use explicit waits for meaningful state rather than fixed delays. For a few reads, clarity is more valuable than combining operations into script execution.

Reliability depends on locating the intended element in the correct frame and reading it after the page reaches the required state. Dynamic applications may replace nodes, making previously stored WebElements stale. Re-locate after rerenders and assert either markup or live state deliberately.

Running Selenium locally has browser and driver setup and compute costs. A remote Selenium grid adds service and network considerations; cost depends on that environment. getAttribute itself does not make a network request to the target site beyond the WebDriver command to the browser already under test.

Or skip the browser setup

If your goal is to capture a page as an image or PDF rather than inspect an element’s attribute, ScreenshotNeo provides a website screenshot API and MCP server. Its single GET request returns a PNG, JPEG, WebP, or PDF. 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
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie/consent banners are accepted like a visitor and removed before capture, along with 60+ known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off.
  • Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers identify the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan.

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.

FAQ

Does getAttribute() read the original HTML response?

No. It reads the element in the current browser DOM. Use a method designed to inspect the network response or page source if you need the original response content.

Can getAttribute() return an absolute URL?

Yes. For a URL attribute such as href, property-first behavior can return the browser-resolved URL. Use the DOM attribute method to read the declared string.

Should I use getAttribute() for checkbox state?

For current selection state, use Selenium’s selected-state method. Use an attribute method only when the test specifically concerns the markup attribute.

Is the method name the same in every language?

No. Python uses snake case (get_attribute); Java and JavaScript use camel case (getAttribute). JavaScript calls are asynchronous and should be awaited.