Read an input’s hint with get_dom_attribute("placeholder") and its current contents with get_property("value"). Selenium has already converted browser text to a Python str; if you see � or mojibake, first establish whether the corruption is in the DOM or only in your terminal, log, or export. That distinction determines whether to investigate HTML decoding or your output pipeline.
Placeholder text and the live value are different things
The HTML Standard defines placeholder as “a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value.” It is instructional text, not data entered by the user. See the WHATWG input placeholder definition.
An <input> can therefore have all of these at once:
- A markup attribute such as
placeholder="Café". - A live DOM
value, initially empty and later changed by typing or JavaScript. - Text that appears in a terminal or file after Selenium has returned it.
Use the first Selenium call for the original hint declared in markup and the second for what the control contains now:
from selenium.webdriver.common.by import By
field = driver.find_element(By.NAME, "search")
placeholder_hint = field.get_dom_attribute("placeholder")
current_value = field.get_property("value")
print("placeholder:", repr(placeholder_hint))
print("current value:", repr(current_value))
get_dom_attribute() reads an attribute declared in the HTML. get_property() reads the current DOM property, which is why it reflects typing and script changes. The Python binding’s get_attribute() method is property-first and falls back to an attribute with the same name. That convenience behavior is useful when you do not care which source wins, but the explicit methods remove ambiguity. The details are documented in Selenium’s Python WebElement API.
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
A complete Selenium example
This example waits for the field, captures both representations, and prints characters in an inspectable form. Replace the URL and locator with those from your page.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
URL = "https://example.com/form"
options = webdriver.ChromeOptions()
# options.add_argument("--headless=new") # enable in CI if required
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 20)
try:
driver.get(URL)
field = wait.until(
EC.presence_of_element_located((By.NAME, "search"))
)
hint = field.get_dom_attribute("placeholder")
value = field.get_property("value")
print("placeholder:", repr(hint))
print("value:", repr(value))
finally:
driver.quit()
repr() exposes leading or trailing whitespace and makes replacement characters visible; it does not repair encoding. If the application fills the field after an API call, wait for the state you need rather than reading immediately:
wait.until(lambda d: field.get_property("value") != "")
value = field.get_property("value")
For an input whose value is intentionally empty, wait for a page-specific condition such as a loading indicator disappearing. Do not use a nonempty-value wait when an empty value is a valid result.
Diagnose where the non-UTF-8 problem occurs
A Selenium result is a Python str, not the original HTTP response bytes. The phrase “non-UTF-8 placeholder” can describe several different cases, so compare the same text at each stage.
Recommended Free Tools
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
Case 1: The DOM itself contains � or mojibake
If repr(field.get_dom_attribute("placeholder")) is already damaged, the browser likely decoded the document bytes using an encoding that did not match the page’s actual content. Check the response’s character-encoding declaration and the document’s applicable meta charset or HTTP header. The parsing rules are described in the WHATWG HTML parsing specification, and declaration rules are in specifying document character encoding. The WHATWG Encoding Standard explains UTF-8 and legacy decoding algorithms.
Use browser developer tools’ Network and document inspection to determine what encoding was declared and what text reached the DOM. If you separately fetch the response for diagnosis, preserve its raw bytes and decode them once with the encoding the server actually declares. Do not guess an encoding merely because one character looks unusual.
Case 2: The DOM is correct, but your output is damaged
If the browser displays the expected character and repr() shows it correctly, Selenium has done its job. The failure is later: a console encoding, log handler, file encoding, database connection, or CSV export. Configure that destination explicitly. For a UTF-8 text file, for example:
with open("placeholder.txt", "w", encoding="utf-8", newline="") as fh:
fh.write(placeholder_hint or "")
On a terminal, inspect the environment and logger configuration rather than applying a second decode to an already-correct Python string.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
Case 3: You are reading the wrong representation
If you call get_property("value") on an untouched field, an empty string is expected even when a placeholder is visible. Conversely, get_dom_attribute("placeholder") will not tell you what a user typed. Compare both values before changing any encoding code.
Choose the correct element API
Selenium’s element-information guidance covers attributes, properties, and visible content in its information about web elements documentation. Use the API that matches the data you need:
| What you need | Call | Why |
|---|---|---|
| Hint originally declared in HTML | element.get_dom_attribute("placeholder") |
Reads the markup attribute. |
| Current text entered or assigned to an input | element.get_property("value") |
Reads the live DOM property. |
| Property-first convenience lookup | element.get_attribute("value") |
Property first, then same-named attribute fallback. |
| Visible text in a normal element | element.text (or a suitable text property) |
Inputs do not expose their placeholder through ordinary visible-text retrieval. |
Use a locator that identifies the actual control. Selenium’s finding elements documentation describes locator strategies such as name, ID, CSS selector, and XPath. A stable ID or name is preferable to a brittle positional XPath.
Handling legacy encodings without corrupting text
Do not repeatedly run .encode("utf-8").decode(...) on every Selenium result. That can turn a recoverable diagnostic into permanent corruption. Instead:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
- Read both the placeholder attribute and live value with the explicit calls above.
- Print them with
repr()and compare them with what the browser visibly renders. - If the DOM is wrong, inspect the server’s declared encoding and the HTML parser’s interpretation.
- If the DOM is right, inspect the terminal, logger, file, database, or export step that changes it.
- Decode raw response bytes only once, using a justified encoding, when you are doing a separate response-level investigation.
A page can legally use a legacy encoding, but Selenium does not expose the original byte sequence through a WebElement string. Your goal is to locate the first stage at which characters changed, not to force every stage to UTF-8 after the fact.
Common failures and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
get_dom_attribute("placeholder") returns None |
The element has no placeholder attribute, or the locator found a different element. | Inspect the element in developer tools, verify the locator, and handle None explicitly. |
Placeholder is visible but get_property("value") is empty |
The field has not been filled; the hint is not the value. | Read the placeholder separately, or type/set a value before reading the property. |
| Value is empty only sometimes | JavaScript populates it asynchronously. | Wait for the application-specific state or value before reading. |
� appears in Selenium output |
The DOM was decoded incorrectly, or the output layer replaced an unsupported character. | Check repr() first, then investigate document encoding versus output encoding. |
Text looks like é or similar mojibake |
Bytes were decoded with one encoding and later interpreted as another. | Find the first incorrect conversion; do not apply another blind encode/decode cycle. |
AttributeError for a Selenium method |
An old Selenium binding may not provide the explicit API. | Check the installed Selenium version and use the current documented Python WebElement methods, preferably after upgrading in a controlled environment. |
StaleElementReferenceException |
The page replaced the input after you located it. | Wait for the replacement and locate the element again immediately before reading. |
| Visible hint is not the expected language | Localization or client-side code changed the attribute after load. | Read the attribute after the locale is established and verify the selected language. |
A reusable helper for tests
Returning both values makes test failures explainable and prevents accidental substitution of a hint for user data:
def read_input_text(element):
return {
"placeholder": element.get_dom_attribute("placeholder"),
"value": element.get_property("value"),
}
result = read_input_text(field)
assert result["placeholder"] is not None
print(result)
Keep the values as Unicode Python strings through your test logic. Choose an explicit encoding only at an output boundary, such as writing a report or sending a byte-oriented protocol.
Or skip the browser setup
If your goal is to capture a page for a debugging report rather than interact with its form, ScreenshotNeo provides a single-request screenshot API. It removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, with the result identified by X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
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 reinstallOutdated 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 matchFor a direct image request, see the ScreenshotNeo API documentation:
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request in Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
And in 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}`);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));
You can still control full-page capture, lazy-image loading, selectors, dark mode, device and retina settings, custom CSS or JavaScript, waits, headers, cookies, user agents, geolocation, blocking rules, PDF output, caching TTL, signed links, asynchronous webhooks, bulk capture, and more. Every plan includes the features; the Free plan includes 1,000 shots per month without a card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.
FAQ
Can I recover the original non-UTF-8 bytes from a WebElement?
No. The WebElement APIs return decoded Python strings. To study original bytes, capture the HTTP response separately and document the encoding used for that decode.
Why does changing the placeholder not change the input value?
They are separate DOM members. A placeholder is a hint shown when the value is empty; assigning one does not enter data into the control.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Should I always use get_dom_attribute() instead of get_attribute()?
Use the explicit method when you need the markup attribute specifically. Use get_attribute() when its property-first behavior is exactly what your test intends.
Frequently Asked Questions
Can I recover the original non-UTF-8 bytes from a WebElement?
No. WebElement methods return decoded Python strings; inspect the HTTP response bytes separately when byte-level diagnosis is required.
Why does changing the placeholder not change the input value?
The placeholder and live value are separate DOM members. A hint does not enter data into the control.
Should I always use get_dom_attribute() instead of get_attribute()?
Use get_dom_attribute() for the declared markup attribute; get_attribute() is property-first and is appropriate only when that behavior is intended.
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.

