In Selenium, what does a Find Element response actually contain, and how does the client use it?
answer
- One fixed JSON key comes back
- The driver names it, not the page
- A UUID-shaped constant from the spec
- Prefix element-, then that fixed UUID
basics
~10 sFind Element returns a JSON object with one fixed key, element-6066-11e4-a52e-4f735466cecf, holding an opaque id the driver assigned to that node. The client wraps that id in a WebElement; no markup travels back.
solid answer
~40 sThe remote end never serialises the node. It answers with a web element reference: a one-member JSON object whose key is the W3C constant `element-6066-11e4-a52e-4f735466cecf` and whose value is an opaque id string the driver invented for that DOM node. The constant is UUID-shaped so it cannot collide with a property a page's own JSON might carry, which lets the client pick element references out of anything `executeScript` returns. The driver keeps a per-browsing-context cache from that id to the real node, so every later command just sends the id back. The Java client stores it as a `RemoteWebElement` holding the id plus its session; `getId()` exposes the raw string. Selenium 4 uses this key only - Selenium 3's JSON Wire `ELEMENT` key is gone.
code
java · 17 linesimport org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebElement;
public class ApprovalHandle {
public static void main(String[] args) {
ChromeDriver driver = new ChromeDriver();
try {
driver.get("https://payroll.internal/approvals");
WebElement approve = driver.findElement(By.id("approve-timesheet-4821"));
System.out.println(((RemoteWebElement) approve).getId());
} finally {
driver.quit();
}
}
}go deeper
Be ready to say that a find gives you back a reference, not the element's markup, and that the driver invented the id inside it.
Explain the mechanics: one fixed W3C key, an opaque driver-assigned value, a per-browsing-context cache from id to node, and the id going back out with every later command.
Show why the shape matters in production: references cannot be persisted, shared between sessions or reconstructed, so any design that stores them across page transitions is building a failure in.
Own the consequence for a suite's architecture - decide where element identity may be held at all, and set the convention that node references never cross a step, a fixture or a process boundary.
## What a find actually sends back When a Selenium test calls `driver.findElement(By.id("approve-timesheet-4821"))` on a payroll approval queue, the client sends one command to the **remote end** - the driver process, such as ChromeDriver, that sits between the test and the browser. The remote end runs the search inside the page. When a node matches, it does **not** serialise that node: no tag name, no attributes, no markup travels back. What comes back is a **web element reference**, a JSON object with exactly one member: ```json {"value": {"element-6066-11e4-a52e-4f735466cecf": "f.8B21C0A4.d.2"}} ``` The outer `value` member is the protocol's ordinary envelope for a successful result. The member inside it is what this topic is about. ## The one key that never changes `element-6066-11e4-a52e-4f735466cecf` is a **constant** defined by the W3C WebDriver specification. It is byte-identical in Chrome, Firefox, Edge and Safari, in every language binding, and for every element in every session - only the string beside it varies. Its UUID shape is deliberate rather than decorative: - A short key such as `element` or `id` could collide with a property a page's own JSON object already carries. - `executeScript` can return arbitrary structures the page built, so the client must be able to decide *this object is a reference, that one is data*. - A fixed, random-looking constant makes that decision safe: the client converts exactly the objects carrying this key into `WebElement` instances and leaves everything else as plain data. - The suffix encodes nothing. It is not a session id, not a hash of the element, and it is not regenerated per run. Selenium 4 speaks W3C WebDriver only. Selenium 3's JSON Wire Protocol used a different key, `ELEMENT`, and that spelling is history - it survives only in old articles and in traffic captured from very old drivers. ## What the id string itself is The value beside the key is an **opaque handle**. ChromeDriver produces one dotted shape, geckodriver produces a UUID; both are private formats, and a test that parses, sorts or predicts one has coupled itself to a driver build. What makes the handle work is the **element cache** on the remote end: a per-**browsing-context** map that the specification calls the *known elements*, from handle to the actual DOM node. Asking for the same node again returns the reference the remote end already issued for it rather than inventing a second one. | The reference is | The reference is not | |---|---| | a key into the driver's own node map | the element's HTML `id` attribute | | assigned by the remote end, per node | anything the test or the page chose | | meaningful only to the session that received it | portable to another session or another run | | valid while the issuing document lives | a durable name for a piece of user interface | ## What the client wraps around it The Java client turns the reference into a `RemoteWebElement` that holds two things: the handle string and the driver that produced it. `RemoteWebElement.getId()` exposes the raw string if you ever need to see it in a log. Every later command against that element - a click on the approve button, a read of the timesheet total - sends the same handle back so the remote end can look the node up again. Nothing about the node is kept on the client side. ## Why this matters on a payroll approval run A test that opens the pending-approvals queue, keeps the handle for timesheet 4821's row, approves it, and then touches that stored element is asking the remote end to resolve a handle whose node may no longer belong to the document that issued it. The handle is not malformed; it is simply no longer resolvable, and the protocol has a dedicated error for exactly that, `stale element reference`. The wire model explains the whole failure class in four steps: 1. The remote end assigns a handle the first time it finds a node. 2. The handle lives in the known-elements cache for that browsing context. 3. A command carrying the handle is dereferenced against that cache. 4. If the node has left its document, or that document is no longer the active one, the command fails rather than guessing at a replacement. Three practical consequences follow: - A handle cannot be written to a file and reused by tomorrow's run. - A handle cannot be shared between two driver sessions driving the same queue. - Two different handles may denote the same visible approve button on two different loads of the page, and the remote end has no notion that they are related.
- Why must a test never parse or predict the id string inside the reference?The format is a driver implementation detail: ChromeDriver emits a dotted string, geckodriver a UUID, and either may change between builds. The specification promises only that the value is opaque and that the driver can resolve it. Any test that reads structure into it breaks on a driver upgrade for no benefit.
- If the same node is found twice in one document, are the two references equal?Yes. The remote end keeps a known-elements map per browsing context and reuses the reference it already issued for a node rather than minting a second one, so both finds yield the same id. The Java client compares `RemoteWebElement` instances by that id. Do not expect equality across documents or sessions.
- What comes back when executeScript returns a DOM element?The same shape: the returned value carries the `element-6066-11e4-a52e-4f735466cecf` key, and the client converts it into a `WebElement` instead of leaving it as a map. That is precisely why the key is a fixed, collision-proof constant - the client has to distinguish references from ordinary page data in an arbitrary returned structure.
The reference is a cloakroom ticket, not the coat: the ticket carries nothing about what you handed over, and it is worthless at any other cloakroom or after this one closes for the night.
saying these in an interview costs you the question
- Says the find command returns the element's HTML
- Thinks the key is the element's id attribute
- Believes the page generates the reference id
- Parses, sorts or predicts the opaque id string
- Expects the same id in a later session