How to Get HTML Attribute Values With Selenium and JavaScript
Read HTML attributes with Selenium’s JavaScript API, choose between attributes and properties, and handle missing values and common edge cases.
In Selenium’s JavaScript bindings, find the element and await getAttribute():
const { Builder, By } = require('selenium-webdriver');
(async () => {
const driver = await new Builder().forBrowser('chrome').build();
try {
await driver.get('https://example.com');
const link = await driver.findElement(By.css('a'));
const href = await link.getAttribute('href');
console.log(href);
} finally {
await driver.quit();
}
})();
Selenium’s getAttribute(name) reads the current attribute when present, but can fall back to a same-named DOM property when the attribute is absent. Use getDomAttribute() when you specifically need the attribute, or getProperty() for the live property. These methods are asynchronous in JavaScript, so await their results. See Selenium’s WebElement API.
Choose the value you actually need
| Method | Reads | Missing behavior | Use it for |
|---|---|---|---|
getAttribute(name) |
Attribute, with fallback to same-named property | null if neither exists |
Selenium’s compatibility behavior when either value is acceptable |
getDomAttribute(name) |
DOM attribute only | null if absent |
Checking markup attributes, including whether a boolean attribute exists |
getProperty(name) |
Live DOM property | Depends on the property; it may exist even without an attribute | Current browser state, such as an input’s edited value |
Native element.getAttribute(name) |
DOM attribute only | null if absent |
Using browser JavaScript explicitly |
For example, an input’s HTML value attribute generally represents its markup default, while the live value property can reflect what a user has typed. Decide whether your assertion concerns initial markup or current state; the two are not interchangeable. Selenium documents the wrapper methods in its JavaScript API, and the native behavior is described by MDN’s Element.getAttribute reference.
Read an attribute, property, or native DOM value
Read only the HTML attribute
const src = await image.getDomAttribute('src');
if (src === null) {
console.log('The src attribute is absent');
} else {
console.log(src);
}
Read the current DOM property
const currentValue = await input.getProperty('value');
console.log(currentValue);
Property values can be strings, booleans, numbers, objects, or other JavaScript values, depending on the property. Do not assume every property result is a string.
Run native JavaScript in the page
const href = await driver.executeScript(
'return arguments[0].getAttribute("href")',
link
);
console.log(href); // string or null
executeScript() runs in the browser context; Selenium passes the WebElement as arguments[0]. This route uses the native DOM method, which returns the attribute’s string value or null when absent. Selenium’s guide covers element information and executing JavaScript.
Handle missing and boolean attributes
Check explicitly for null; absent attributes do not reliably mean an empty string or false. For boolean HTML attributes such as disabled, presence is what matters. Selenium documents boolean attributes as "true" when present and null when absent.
const disabled = await button.getDomAttribute('disabled');
if (disabled !== null) {
console.log('The disabled attribute is present');
}
Use getDomAttribute() to test attribute presence. If you need the current enabled/disabled state as the browser exposes it, inspect the corresponding property or use Selenium’s element state methods where appropriate.
Wait for the element and avoid stale references
A lookup can fail if the page has not rendered the element yet. Wait for the relevant condition instead of adding an arbitrary delay:
const { Builder, By, until } = require('selenium-webdriver');
(async () => {
const driver = await new Builder().forBrowser('chrome').build();
try {
await driver.get('https://example.com');
const link = await driver.wait(
until.elementLocated(By.css('a.example')),
10000,
'Example link did not appear'
);
const href = await link.getDomAttribute('href');
console.log(href);
} finally {
await driver.quit();
}
})();
If an application replaces or rerenders the element after you locate it, the saved WebElement can become stale. Locate it again after the update, then read the value. Selenium’s element information guide describes element retrieval and interaction.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
getAttribute is not a function |
The variable is not a Selenium WebElement, or it is a browser-side element from a different context. | Confirm it came from await driver.findElement(...). For browser-side DOM access, use executeScript() and call native getAttribute() there. |
The result is null |
The attribute is absent and no same-named property fallback applies, or you used getDomAttribute() and the markup has no such attribute. |
Check the selector and inspect the intended attribute/property distinction. Handle null explicitly. |
| The value differs from what appears on screen | You read the markup attribute while the live property changed, or the reverse. | Use getDomAttribute() for markup and getProperty() for current DOM state. |
NoSuchElementError or timeout |
The selector does not match, the page is in another frame, or rendering has not completed. | Verify the selector, switch to the correct frame if needed, and wait for the element to appear. |
StaleElementReferenceError |
The DOM node was detached or replaced after lookup. | Locate the element again after the page update, then read its value. |
| Promise or unexpected object output | The async call was not awaited, or the chosen property returns a non-string value. | Use await or .then(); inspect the property’s type and convert only if the test requires a string. |
Performance, reliability, and cost
For one value, a direct WebElement call is the simplest choice. Each separate WebDriver command adds a round trip between your test and the browser driver; if you need several values from the same element, a single executeScript() call can read them together. Keep waits tied to a real page condition, and reacquire elements after rerenders to reduce flaky lookups.
For a normal Selenium setup, account for the runtime and maintenance of a browser and driver, plus the compute used to run them. The research sources do not provide benchmark or pricing figures, so performance and cost depend on the environment and workload.
Or skip the browser setup
If your goal is a visual record of a page rather than an assertion about a particular DOM value, ScreenshotNeo returns a screenshot or PDF from one GET request. Its API accepts a URL, with options for full-page capture, element selectors, custom waits, and more. See the 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}`);
ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, with response headers identifying the page verdict and billing status. An MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Does Selenium JavaScript return a promise from getAttribute?
Yes. Await the result or use .then().
Should I use getAttribute or getDomAttribute?
Use getDomAttribute() when the HTML attribute itself is the subject of the check. Selenium’s getAttribute() can fall back to a property.
Can I get a resolved absolute link URL?
Read the live href property when you want the browser-resolved URL. The href attribute gives the value stored in markup.
Does the native DOM method return an empty string when absent?
No. Native Element.getAttribute() returns null for an absent attribute.


