Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Selenium’s script-execution API to inspect the element’s immediate childNodes, keep only nodes whose nodeType is Node.TEXT_NODE, and join those values. Selenium’s normal .text or Java getText() includes visible text from nested elements, so it cannot provide direct-text-only output.
The direct-text solution
Locate the element as usual, pass that WebElement into browser-side JavaScript, and filter its immediate child nodes. The essential expression is:
Array.from(arguments[0].childNodes)
.filter(n => n.nodeType === Node.TEXT_NODE)
.map(n => n.nodeValue.trim())
.filter(Boolean)
.join(' ')
This reads text nodes that belong directly to the target element. Text inside a nested <span>, link, emphasis tag, or any other descendant element is excluded. The example above returns a normalized string: each direct node is trimmed, empty nodes are removed, and the remaining pieces are separated by one space.
Why Selenium .text includes nested text
Selenium’s ordinary text accessors are rendered-text accessors, not direct-child accessors. The JavaScript WebElement API describes getText() as returning visible text “including sub-elements,” and the Selenium Java API uses the same semantics. Selenium’s element-information documentation calls this rendered text. Therefore, an element such as:
#1 Best Overall
- KEYBOARD: The keyboard works for Windows with hot keys that enable easy access to Media, My Computer, Mute, Volume up/down, and Calculator
- EASY SETUP: Experience simple installation with the USB wired connection
- VERSATILE COMPATIBILITY: This keyboard is designed to work with multiple Windows versions, including Vista, 7, 8, 10 offering broad compatibility across devices.
- SLEEK DESIGN: The elegant black color of the wired keyboard complements your tech and decor, adding a stylish and cohesive look to any setup without sacrificing function.
- FULL-SIZED CONVENIENCE: The standard QWERTY layout of this keyboard set offers a familiar typing experience, ideal for both professional tasks and personal use.
<div class="example">
Alpha <span>nested</span> Omega
</div>
can produce Alpha nested Omega through .text or getText(). That behavior is useful when you want what a user sees, but it is wrong when the nested value must be ignored.
The DOM gives you the distinction Selenium’s text accessor does not. childNodes contains every immediate child node, including text nodes and element nodes. children contains only child elements, so using it would lose the text you need. Filtering for Node.TEXT_NODE keeps direct text while skipping nested elements and everything below them.
Python: complete implementation
In Python Selenium, call execute_script with the located element as an argument:
Free tools Windows power users keep installed
One-click scans. No signup required.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
try:
driver.get("https://example.com")
el = driver.find_element(By.CSS_SELECTOR, "div.example")
direct_text = driver.execute_script(
"return Array.from(arguments[0].childNodes)"
".filter(n => n.nodeType === Node.TEXT_NODE)"
".map(n => n.nodeValue.trim())"
".filter(Boolean)"
".join(' ')",
el,
)
print(direct_text)
finally:
driver.quit()
execute_script serializes the returned JavaScript string back to Python. Passing el as an argument is preferable to interpolating a selector into JavaScript: Selenium transfers the actual element reference, and the script operates on exactly the element you located.
A reusable Python helper
def direct_text(driver, element, *, normalize=True):
if normalize:
return driver.execute_script(
"return Array.from(arguments[0].childNodes)"
".filter(n => n.nodeType === Node.TEXT_NODE)"
".map(n => n.nodeValue.trim())"
".filter(Boolean)"
".join(' ')",
element,
)
return driver.execute_script(
"return Array.from(arguments[0].childNodes)"
".filter(n => n.nodeType === Node.TEXT_NODE)"
".map(n => n.nodeValue)",
element,
)
The normalized branch returns one string. The raw branch returns an array of the original direct-node values, which is safer when whitespace itself carries meaning. You can concatenate that array yourself under rules appropriate to the page.
Java: complete implementation
Java uses JavascriptExecutor and casts the returned value to String:
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class DirectText {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
driver.get("https://example.com");
WebElement el = driver.findElement(By.cssSelector("div.example"));
String directText = (String) ((JavascriptExecutor) driver).executeScript(
"return Array.from(arguments[0].childNodes)"
+ ".filter(n => n.nodeType === Node.TEXT_NODE)"
+ ".map(n => n.nodeValue.trim())"
+ ".filter(Boolean)"
+ ".join(' ')",
el
);
System.out.println(directText);
} finally {
driver.quit();
}
}
}
The Java API documentation for Selenium 4.28.0 also notes an important XPath detail: .// scopes a search to descendants of the current element, while // starts from the document. That distinction matters when locating the parent before extracting its direct text.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
- Reliable Plug and Play: The USB receiver provides a reliable wireless connection up to 33 ft (1), so you can forget about drop-outs and delays and you can take it wherever you use your computer
- Type in Comfort: The design of this keyboard creates a comfortable typing experience thanks to the low-profile, quiet keys and standard layout with full-size F-keys, number pad, and arrow keys
- Durable and Resilient: This full-size wireless keyboard features a spill-resistant design (2), durable keys and sturdy tilt legs with adjustable height
- Long Battery Life: MK270 combo features a 36-month keyboard and 12-month mouse battery life (3), along with on/off switches allowing you to go months without the hassle of changing batteries
- Easy to Use: This wireless keyboard and mouse combo features 8 multimedia hotkeys for instant access to the Internet, email, play/pause, and volume so you can easily check out your favorite sites
Other Selenium language bindings
Bindings that expose JavaScript execution use the same browser-side expression. Find the element with that binding’s normal locator method, pass the element as a script argument, and read the returned string. Confirm the exact method signature for the Selenium version used by your project; the DOM algorithm itself does not change.
Whitespace: choose your output policy
HTML source frequently places indentation and line breaks between tags. Those characters can be represented by text nodes. A direct-node filter therefore needs an explicit whitespace policy.
Normalized human-readable text
Use trim(), discard empty values, and join with one space when the result is a label, title, or assertion where formatting is irrelevant. The Python and Java examples use this policy.
Exact source spacing
If spaces, line breaks, or punctuation are significant, do not trim. Return each matching node’s nodeValue and preserve or concatenate the values according to the source markup. Trimming and joining changes the original spacing, even though it usually produces a more convenient test value.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Several direct pieces around a nested element
For <div>Alpha <span>nested</span> Omega</div>, the direct nodes are Alpha and Omega. The span’s nested value is not a direct node. A normalized policy yields Alpha Omega; an exact policy retains the spaces present in the two source nodes.
DOM and visibility semantics
.text applies Selenium’s visible/rendered-text behavior, including text from descendants. The JavaScript method reads DOM text nodes instead. It should not be described as a visibility filter: a text node may exist in the DOM even when CSS prevents it from being rendered. If your test requires visible-only direct text, first establish the visibility condition separately, then apply the direct-node extraction to the element that meets that condition.
Likewise, textContent is not a shortcut. Reading element.textContent aggregates text from descendants, which is exactly what this technique is meant to avoid.
Rank #3
- All-day Comfort: The design of this standard keyboard creates a comfortable typing experience thanks to the deep-profile keys and full-size standard layout with F-keys and number pad
- Easy to Set-up and Use: Set-up couldn't be easier, you simply plug in this corded keyboard via USB on your desktop or laptop and start using right away without any software installation
- Compatibility: This full-size keyboard is compatible with Windows 7, 8, 10 or later, plus it's a reliable and durable partner for your desk at home, or at work
- Spill-proof: This durable keyboard features a spill-resistant design (1), anti-fade keys and sturdy tilt legs with adjustable height, meaning this keyboard is built to last
- Plastic parts in K120 include 51% certified post-consumer recycled plastic*
Dynamic pages and collection timing
childNodes is a live NodeList. Page scripts can insert, remove, or replace nodes while you work with it. Array.from(arguments[0].childNodes) takes a snapshot before filtering, so the operation works on one immediate-node list rather than a collection that can change during iteration.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteYou still need to locate the element at the right time. If the page renders the container asynchronously, wait for the element with your normal Selenium wait strategy before calling the script. If a framework replaces that element after you locate it, Selenium can report a stale-element failure; locate the current element again and then extract its direct nodes.
Common mistakes and fixes
Using .text or getText()
Symptom: nested labels, links, or badges appear in the result.
Cause: Selenium’s accessor intentionally includes visible descendant text.
Fix: execute the childNodes filter shown above.
Using children
Symptom: the result is empty even though the element contains visible words.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteCause: children returns element nodes only and omits text nodes.
Fix: use childNodes and test nodeType === Node.TEXT_NODE.
Rank #4
- 【Dreamy Rainbow Gaming Keyboard】K521 Gaming Keyboard Adopts a Different LED Backlight Design, Upgraded on the Traditional LED Backlight Effect, Making the Light More Penetrating, Giving You a More Dazzling Visual Effect, Making Your Gaming Process More Enjoyable
- 【One Touch Opens & Visual Feast】The K521 Red Dragon Keyboard has a One-Touch on/off Lighting Button for Added Convenience. It also has a Three-Position Adjustable Breathing Mode and a Four-Position Adjustable Brightness Lighting Mode
- 【Mechanical Feeling & Fast Tapping】The PC Keyboard Keys are Designed for Mechanical Feeling, Giving You a Better Feel During Use and the Ability to Trigger Keys Quickly, Allowing You to Win All Your Games
- 【19 Keys Anti-Ghosting Keyboard】Anti-Ghosting Ensures Every Button Can Be Triggered. This Allows You to Trigger Key Combinations In The Game Accurately, And Each Skill Can Be Accurately Released to Increase Your Winning Rate. Redragon K521 Will Be Your Perfect Partner
- 【12 Multimedia Combination Keys】The K521 Wired Gaming Keyboard is Equipped with 12 Multimedia Keys That Can Greatly Enhance Your Gaming/Office Efficiency and Make It More Convenient to Use
Using textContent on the parent
Symptom: descendant text is still present.
Cause: textContent aggregates the entire subtree.
Fix: inspect only the parent’s immediate child-node snapshot.
Unexpected blank strings
Symptom: the raw result contains empty or whitespace-only entries.
Cause: indentation and line breaks between tags are text nodes.
Fix: trim and filter empty values for normalized output, or deliberately preserve them when exact source formatting matters.
A stale-element exception
Symptom: script execution fails after a page update.
Cause: the framework replaced the DOM node represented by your WebElement.
Fix: wait for the page’s update to settle, find the element again, and pass the new reference to the script.
Best Value
- All-day Comfort: This USB keyboard creates a comfortable and familiar typing experience thanks to the deep-profile keys and standard full-size layout with all F-keys, number pad and arrow keys
- Built to Last: The spill-proof (2) design and durable print characters keep you on track for years to come despite any on-the-job mishaps; it’s a reliable partner for your desk at home, or at work
- Long-lasting Battery Life: A 24-month battery life (4) means you can go for 2 years without the hassle of changing batteries of your wireless full-size keyboard
- Simply plug the USB receiver into a USB port on your desktop, laptop or netbook computer and start using the keyboard right away without any software installation
- Simply Wireless: Forget about drop-outs and delays thanks to a strong, reliable wireless connection with up to 33 ft range (5); K270 is compatible with Windows 7, 8, 10 or later
An XPath locator finds the wrong scope
Symptom: extraction runs against an element outside the intended container.
Cause: XPath beginning with // starts from the document, whereas .// searches below the current element.
Fix: use the relative form when searching from a previously located WebElement.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Assertions and test design
Decide whether your assertion is about source structure or what a user sees. Use Selenium’s rendered-text accessor for a user-visible label that legitimately includes descendants. Use the direct-node script when the contract specifically says that only text written immediately in the container counts.
Keep the extraction policy stable across tests. A helper that always normalizes whitespace prevents one test from silently comparing raw indentation while another compares a collapsed string. Conversely, expose a raw mode when exact spacing is part of the requirement instead of hiding that decision inside a generic helper.
For diagnostic failures, log both the normalized direct value and (when safe) the list of raw direct-node values. That makes it clear whether a failure came from an unexpected nested element, whitespace-only nodes, or a genuinely changed direct label.
Performance and reliability considerations
The script examines only the target element’s immediate children; it does not recursively walk the subtree. That keeps the DOM work proportional to the number of direct nodes rather than all descendants. The dominant cost in a normal test is usually browser communication and page state, not the short filter itself.
Run the script after the element is present and stable, and avoid repeatedly extracting the same value inside a tight loop when one read can be reused. If the page mutates continuously, take a fresh element reference at the point of extraction and use the Array.from snapshot so one call has a consistent immediate-node view.
Or skip the browser setup
If you need a rendered screenshot or PDF of a page for a test artifact rather than direct DOM text, ScreenshotNeo provides a single HTTP request and an MCP server for AI clients. Its API can accept consent banners before capture and remove more than 60 known consent platforms, newsletter popups, and chat widgets; failed loads, bot checks or CAPTCHAs, blank pages, timeouts, and cache hits are not billed. Every response identifies the page verdict and billing status in headers.
See the ScreenshotNeo API documentation for options such as full-page capture, CSS-selector element capture, custom JavaScript, waits, blocking rules, device presets, PDFs, signed links, asynchronous jobs, and bulk capture.
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}`);
The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots, and every feature is included on every plan. Create a free ScreenshotNeo account.
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.

