# class: ElementHandle
* since: v1.8
* extends: [JSHandle]
ElementHandle represents an in-page DOM element. ElementHandles can be created with the [`method: Page.querySelector`] method.
:::caution Discouraged
The use of ElementHandle is discouraged, use [Locator] objects and web-first assertions instead.
:::
```js
const hrefElement = await page.$('a');
await hrefElement.click();
```
```java
ElementHandle hrefElement = page.querySelector("a");
hrefElement.click();
```
```python async
href_element = await page.query_selector("a")
await href_element.click()
```
```python sync
href_element = page.query_selector("a")
href_element.click()
```
```csharp
var handle = await page.QuerySelectorAsync("a");
await handle.ClickAsync();
```
ElementHandle prevents DOM element from garbage collection unless the handle is disposed with
[`method: JSHandle.dispose`]. ElementHandles are auto-disposed when their origin frame gets navigated.
ElementHandle instances can be used as an argument in [`method: Page.evalOnSelector`] and [`method: Page.evaluate`] methods.
The difference between the [Locator] and ElementHandle is that the ElementHandle points to a particular element, while [Locator] captures the logic of how to retrieve an element.
In the example below, handle points to a particular DOM element on page. If that element changes text or is used by React to render an entirely different component, handle is still pointing to that very DOM element. This can lead to unexpected behaviors.
```js
const handle = await page.$('text=Submit');
// ...
await handle.hover();
await handle.click();
```
```java
ElementHandle handle = page.querySelector("text=Submit");
handle.hover();
handle.click();
```
```python async
handle = await page.query_selector("text=Submit")
await handle.hover()
await handle.click()
```
```python sync
handle = page.query_selector("text=Submit")
handle.hover()
handle.click()
```
```csharp
var handle = await page.QuerySelectorAsync("text=Submit");
await handle.HoverAsync();
await handle.ClickAsync();
```
With the locator, every time the `element` is used, up-to-date DOM element is located in the page using the selector. So in the snippet below, underlying DOM element is going to be located twice.
```js
const locator = page.getByText('Submit');
// ...
await locator.hover();
await locator.click();
```
```java
Locator locator = page.getByText("Submit");
locator.hover();
locator.click();
```
```python async
locator = page.get_by_text("Submit")
await locator.hover()
await locator.click()
```
```python sync
locator = page.get_by_text("Submit")
locator.hover()
locator.click()
```
```csharp
var locator = page.GetByText("Submit");
await locator.HoverAsync();
await locator.ClickAsync();
```
## async method: ElementHandle.boundingBox
* since: v1.8
- returns: <[null]|[Object]>
- `x` <[float]> the x coordinate of the element in pixels.
- `y` <[float]> the y coordinate of the element in pixels.
- `width` <[float]> the width of the element in pixels.
- `height` <[float]> the height of the element in pixels.
This method returns the bounding box of the element, or `null` if the element is not visible. The bounding box is
calculated relative to the main frame viewport - which is usually the same as the browser window.
Scrolling affects the returned bounding box, similarly to
[Element.getBoundingClientRect](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect). That
means `x` and/or `y` may be negative.
Elements from child frames return the bounding box relative to the main frame, unlike the
[Element.getBoundingClientRect](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).
Assuming the page is static, it is safe to use bounding box coordinates to perform input. For example, the following
snippet should click the center of the element.
```js
const box = await elementHandle.boundingBox();
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
```
```java
BoundingBox box = elementHandle.boundingBox();
page.mouse().click(box.x + box.width / 2, box.y + box.height / 2);
```
```python async
box = await element_handle.bounding_box()
await page.mouse.click(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2)
```
```python sync
box = element_handle.bounding_box()
page.mouse.click(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2)
```
```csharp
var box = await elementHandle.BoundingBoxAsync();
await page.Mouse.ClickAsync(box.X + box.Width / 2, box.Y + box.Height / 2);
```
## async method: ElementHandle.check
* since: v1.8
This method checks the element by performing the following steps:
1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
checked, this method returns immediately.
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked. If not, this method throws.
If the element is detached from the DOM at any moment during the action, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
[TimeoutError]. Passing zero timeout disables this.
### option: ElementHandle.check.position = %%-input-position-%%
* since: v1.11
### option: ElementHandle.check.force = %%-input-force-%%
* since: v1.8
### option: ElementHandle.check.noWaitAfter = %%-input-no-wait-after-%%
* since: v1.8
### option: ElementHandle.check.timeout = %%-input-timeout-%%
* since: v1.8
### option: ElementHandle.check.trial = %%-input-trial-%%
* since: v1.11
## async method: ElementHandle.clear
* since: v1.28
This method waits for [actionability](../actionability.md) checks, focuses the element, clears it and triggers an `input` event after clearing.
If the target element is not an ``, `