0
# Element Location
1
2
Modern element location and interaction using the Locator API with built-in auto-waiting, retry logic, and robust element interaction methods. The Locator API is the recommended approach for element interaction in Playwright.
3
4
## Capabilities
5
6
### Locator Creation
7
8
Create locators using various strategies including CSS selectors, text content, ARIA roles, and semantic attributes.
9
10
```python { .api }
11
class Page:
12
def locator(self, selector: str) -> Locator:
13
"""
14
Create locator for elements matching selector.
15
16
Args:
17
selector: CSS selector, text selector, or XPath
18
19
Returns:
20
Locator: Element locator with auto-waiting
21
"""
22
23
def get_by_role(
24
self,
25
role: str,
26
checked: Optional[bool] = None,
27
disabled: Optional[bool] = None,
28
expanded: Optional[bool] = None,
29
include_hidden: Optional[bool] = None,
30
level: Optional[int] = None,
31
name: Union[str, Pattern, None] = None,
32
pressed: Optional[bool] = None,
33
selected: Optional[bool] = None,
34
exact: Optional[bool] = None
35
) -> Locator:
36
"""
37
Create locator by ARIA role.
38
39
Args:
40
role: ARIA role (button, textbox, heading, etc.)
41
checked: Checkbox/radio checked state
42
disabled: Element disabled state
43
expanded: Element expanded state
44
include_hidden: Include hidden elements
45
level: Heading level for heading role
46
name: Accessible name pattern
47
pressed: Button pressed state
48
selected: Option selected state
49
exact: Exact name match
50
51
Returns:
52
Locator: Role-based locator
53
"""
54
55
def get_by_text(
56
self,
57
text: Union[str, Pattern],
58
exact: Optional[bool] = None
59
) -> Locator:
60
"""
61
Create locator by text content.
62
63
Args:
64
text: Text content or pattern
65
exact: Exact text match
66
67
Returns:
68
Locator: Text-based locator
69
"""
70
71
def get_by_label(
72
self,
73
text: Union[str, Pattern],
74
exact: Optional[bool] = None
75
) -> Locator:
76
"""
77
Create locator by associated label text.
78
79
Args:
80
text: Label text or pattern
81
exact: Exact text match
82
83
Returns:
84
Locator: Label-based locator
85
"""
86
87
def get_by_placeholder(
88
self,
89
text: Union[str, Pattern],
90
exact: Optional[bool] = None
91
) -> Locator:
92
"""
93
Create locator by placeholder text.
94
95
Args:
96
text: Placeholder text or pattern
97
exact: Exact text match
98
99
Returns:
100
Locator: Placeholder-based locator
101
"""
102
103
def get_by_alt_text(
104
self,
105
text: Union[str, Pattern],
106
exact: Optional[bool] = None
107
) -> Locator:
108
"""
109
Create locator by alt text attribute.
110
111
Args:
112
text: Alt text or pattern
113
exact: Exact text match
114
115
Returns:
116
Locator: Alt text-based locator
117
"""
118
119
def get_by_title(
120
self,
121
text: Union[str, Pattern],
122
exact: Optional[bool] = None
123
) -> Locator:
124
"""
125
Create locator by title attribute.
126
127
Args:
128
text: Title text or pattern
129
exact: Exact text match
130
131
Returns:
132
Locator: Title-based locator
133
"""
134
135
def get_by_test_id(self, test_id: str) -> Locator:
136
"""
137
Create locator by test ID attribute.
138
139
Args:
140
test_id: Test identifier value
141
142
Returns:
143
Locator: Test ID-based locator
144
"""
145
146
def frame_locator(self, selector: str) -> FrameLocator:
147
"""
148
Create frame locator for iframe elements.
149
150
Args:
151
selector: Frame selector
152
153
Returns:
154
FrameLocator: Frame locator
155
"""
156
```
157
158
### Locator Operations
159
160
Interact with elements through locators with automatic waiting and retry logic.
161
162
```python { .api }
163
class Locator:
164
page: Page
165
first: Locator
166
last: Locator
167
168
def click(
169
self,
170
modifiers: Optional[List[str]] = None,
171
position: Optional[Position] = None,
172
delay: Optional[float] = None,
173
button: Optional[str] = None,
174
click_count: Optional[int] = None,
175
timeout: Optional[float] = None,
176
force: Optional[bool] = None,
177
no_wait_after: Optional[bool] = None,
178
trial: Optional[bool] = None
179
) -> None:
180
"""
181
Click element.
182
183
Args:
184
modifiers: Modifier keys ('Alt', 'Control', 'Meta', 'Shift')
185
position: Click position relative to element
186
delay: Delay between mousedown and mouseup
187
button: Mouse button ('left', 'right', 'middle')
188
click_count: Number of clicks
189
timeout: Action timeout in milliseconds
190
force: Skip actionability checks
191
no_wait_after: Don't wait for navigation
192
trial: Perform checks without action
193
"""
194
195
def dblclick(
196
self,
197
modifiers: Optional[List[str]] = None,
198
position: Optional[Position] = None,
199
delay: Optional[float] = None,
200
button: Optional[str] = None,
201
timeout: Optional[float] = None,
202
force: Optional[bool] = None,
203
no_wait_after: Optional[bool] = None,
204
trial: Optional[bool] = None
205
) -> None:
206
"""Double-click element."""
207
208
def fill(
209
self,
210
value: str,
211
timeout: Optional[float] = None,
212
no_wait_after: Optional[bool] = None,
213
force: Optional[bool] = None
214
) -> None:
215
"""
216
Fill input element with value.
217
218
Args:
219
value: Value to fill
220
timeout: Action timeout in milliseconds
221
no_wait_after: Don't wait for navigation
222
force: Skip actionability checks
223
"""
224
225
def type(
226
self,
227
text: str,
228
delay: Optional[float] = None,
229
timeout: Optional[float] = None,
230
no_wait_after: Optional[bool] = None
231
) -> None:
232
"""
233
Type text character by character.
234
235
Args:
236
text: Text to type
237
delay: Delay between keystrokes
238
timeout: Action timeout in milliseconds
239
no_wait_after: Don't wait for navigation
240
"""
241
242
def press(
243
self,
244
key: str,
245
delay: Optional[float] = None,
246
timeout: Optional[float] = None,
247
no_wait_after: Optional[bool] = None
248
) -> None:
249
"""
250
Press key on element.
251
252
Args:
253
key: Key to press ('Enter', 'Escape', etc.)
254
delay: Delay between keydown and keyup
255
timeout: Action timeout in milliseconds
256
no_wait_after: Don't wait for navigation
257
"""
258
259
def check(
260
self,
261
timeout: Optional[float] = None,
262
force: Optional[bool] = None,
263
no_wait_after: Optional[bool] = None,
264
trial: Optional[bool] = None
265
) -> None:
266
"""Check checkbox or radio button."""
267
268
def uncheck(
269
self,
270
timeout: Optional[float] = None,
271
force: Optional[bool] = None,
272
no_wait_after: Optional[bool] = None,
273
trial: Optional[bool] = None
274
) -> None:
275
"""Uncheck checkbox."""
276
277
def select_option(
278
self,
279
value: Union[str, List[str], None] = None,
280
index: Union[int, List[int], None] = None,
281
label: Union[str, List[str], None] = None,
282
element: Union[ElementHandle, List[ElementHandle], None] = None,
283
timeout: Optional[float] = None,
284
force: Optional[bool] = None,
285
no_wait_after: Optional[bool] = None
286
) -> List[str]:
287
"""
288
Select option(s) in select element.
289
290
Returns:
291
List[str]: Selected option values
292
"""
293
294
def set_input_files(
295
self,
296
files: Union[str, List[str], FilePayload, List[FilePayload]],
297
timeout: Optional[float] = None,
298
no_wait_after: Optional[bool] = None
299
) -> None:
300
"""Set files for file input element."""
301
302
def hover(
303
self,
304
modifiers: Optional[List[str]] = None,
305
position: Optional[Position] = None,
306
timeout: Optional[float] = None,
307
force: Optional[bool] = None,
308
trial: Optional[bool] = None
309
) -> None:
310
"""Hover over element."""
311
312
def focus(
313
self,
314
timeout: Optional[float] = None
315
) -> None:
316
"""Focus element."""
317
318
def clear(
319
self,
320
timeout: Optional[float] = None,
321
no_wait_after: Optional[bool] = None,
322
force: Optional[bool] = None
323
) -> None:
324
"""Clear input element."""
325
326
def scroll_into_view_if_needed(
327
self,
328
timeout: Optional[float] = None
329
) -> None:
330
"""Scroll element into view if needed."""
331
```
332
333
### Locator Filtering and Chaining
334
335
Refine and combine locators for precise element targeting.
336
337
```python { .api }
338
class Locator:
339
def nth(self, index: int) -> Locator:
340
"""
341
Get nth matching element.
342
343
Args:
344
index: Element index (0-based)
345
346
Returns:
347
Locator: Nth element locator
348
"""
349
350
def filter(
351
self,
352
has_text: Union[str, Pattern, None] = None,
353
has_not_text: Union[str, Pattern, None] = None,
354
has: Optional[Locator] = None,
355
has_not: Optional[Locator] = None
356
) -> Locator:
357
"""
358
Filter locator by additional criteria.
359
360
Args:
361
has_text: Element must contain text
362
has_not_text: Element must not contain text
363
has: Element must contain descendant
364
has_not: Element must not contain descendant
365
366
Returns:
367
Locator: Filtered locator
368
"""
369
370
def and_(self, locator: Locator) -> Locator:
371
"""
372
Logical AND with another locator.
373
374
Args:
375
locator: Locator to combine with AND
376
377
Returns:
378
Locator: Combined locator
379
"""
380
381
def or_(self, locator: Locator) -> Locator:
382
"""
383
Logical OR with another locator.
384
385
Args:
386
locator: Locator to combine with OR
387
388
Returns:
389
Locator: Combined locator
390
"""
391
392
def locator(self, selector: str) -> Locator:
393
"""
394
Find locator relative to this locator.
395
396
Args:
397
selector: Relative selector
398
399
Returns:
400
Locator: Relative locator
401
"""
402
```
403
404
### Element State Queries
405
406
Check element states with automatic waiting and retry.
407
408
```python { .api }
409
class Locator:
410
def is_checked(
411
self,
412
timeout: Optional[float] = None
413
) -> bool:
414
"""
415
Check if element is checked.
416
417
Args:
418
timeout: Query timeout in milliseconds
419
420
Returns:
421
bool: True if checked
422
"""
423
424
def is_disabled(
425
self,
426
timeout: Optional[float] = None
427
) -> bool:
428
"""Check if element is disabled."""
429
430
def is_editable(
431
self,
432
timeout: Optional[float] = None
433
) -> bool:
434
"""Check if element is editable."""
435
436
def is_enabled(
437
self,
438
timeout: Optional[float] = None
439
) -> bool:
440
"""Check if element is enabled."""
441
442
def is_hidden(
443
self,
444
timeout: Optional[float] = None
445
) -> bool:
446
"""Check if element is hidden."""
447
448
def is_visible(
449
self,
450
timeout: Optional[float] = None
451
) -> bool:
452
"""Check if element is visible."""
453
454
def count(self) -> int:
455
"""
456
Get number of matching elements.
457
458
Returns:
459
int: Element count
460
"""
461
```
462
463
### Content Access
464
465
Get element content and attributes.
466
467
```python { .api }
468
class Locator:
469
def text_content(
470
self,
471
timeout: Optional[float] = None
472
) -> Optional[str]:
473
"""
474
Get element text content.
475
476
Args:
477
timeout: Query timeout in milliseconds
478
479
Returns:
480
Optional[str]: Text content
481
"""
482
483
def inner_text(
484
self,
485
timeout: Optional[float] = None
486
) -> str:
487
"""
488
Get element inner text.
489
490
Args:
491
timeout: Query timeout in milliseconds
492
493
Returns:
494
str: Inner text
495
"""
496
497
def inner_html(
498
self,
499
timeout: Optional[float] = None
500
) -> str:
501
"""Get element inner HTML."""
502
503
def input_value(
504
self,
505
timeout: Optional[float] = None
506
) -> str:
507
"""Get input element value."""
508
509
def get_attribute(
510
self,
511
name: str,
512
timeout: Optional[float] = None
513
) -> Optional[str]:
514
"""
515
Get element attribute value.
516
517
Args:
518
name: Attribute name
519
timeout: Query timeout in milliseconds
520
521
Returns:
522
Optional[str]: Attribute value
523
"""
524
525
def all_text_contents(self) -> List[str]:
526
"""
527
Get text content of all matching elements.
528
529
Returns:
530
List[str]: Text contents
531
"""
532
533
def all_inner_texts(self) -> List[str]:
534
"""
535
Get inner text of all matching elements.
536
537
Returns:
538
List[str]: Inner texts
539
"""
540
```
541
542
### Utilities
543
544
Additional locator utilities for waiting and screenshots.
545
546
```python { .api }
547
class Locator:
548
def wait_for(
549
self,
550
state: Optional[str] = None,
551
timeout: Optional[float] = None
552
) -> None:
553
"""
554
Wait for locator to reach state.
555
556
Args:
557
state: Element state ('attached', 'detached', 'visible', 'hidden')
558
timeout: Wait timeout in milliseconds
559
"""
560
561
def bounding_box(
562
self,
563
timeout: Optional[float] = None
564
) -> Optional[FloatRect]:
565
"""
566
Get element bounding box.
567
568
Args:
569
timeout: Query timeout in milliseconds
570
571
Returns:
572
Optional[FloatRect]: Element bounds
573
"""
574
575
def screenshot(
576
self,
577
timeout: Optional[float] = None,
578
type: Optional[str] = None,
579
path: Optional[str] = None,
580
quality: Optional[int] = None,
581
omit_background: Optional[bool] = None,
582
animations: Optional[str] = None,
583
caret: Optional[str] = None,
584
scale: Optional[str] = None,
585
mask: Optional[List[Locator]] = None
586
) -> bytes:
587
"""
588
Take element screenshot.
589
590
Args:
591
timeout: Screenshot timeout in milliseconds
592
type: Image type ('png', 'jpeg')
593
path: File path to save screenshot
594
quality: JPEG quality (0-100)
595
omit_background: Hide default background
596
animations: Handle animations ('disabled', 'allow')
597
caret: Handle text caret ('hide', 'initial')
598
scale: Viewport scale ('css', 'device')
599
mask: Elements to mask in screenshot
600
601
Returns:
602
bytes: Screenshot data
603
"""
604
```
605
606
## Usage Examples
607
608
### Semantic Element Location
609
610
```python
611
from playwright.sync_api import sync_playwright
612
613
with sync_playwright() as p:
614
browser = p.chromium.launch()
615
page = browser.new_page()
616
617
page.goto("https://example.com")
618
619
# Locate by role and name
620
submit_button = page.get_by_role("button", name="Submit")
621
submit_button.click()
622
623
# Locate by text content
624
error_message = page.get_by_text("Please fill required fields")
625
assert error_message.is_visible()
626
627
# Locate by label
628
email_input = page.get_by_label("Email Address")
629
email_input.fill("user@example.com")
630
631
# Locate by placeholder
632
search_input = page.get_by_placeholder("Search...")
633
search_input.type("playwright")
634
635
browser.close()
636
```
637
638
### Locator Filtering and Chaining
639
640
```python
641
with sync_playwright() as p:
642
browser = p.chromium.launch()
643
page = browser.new_page()
644
645
page.goto("https://example.com/products")
646
647
# Filter products by text
648
product_cards = page.locator(".product-card")
649
laptop_cards = product_cards.filter(has_text="Laptop")
650
651
# Get specific product
652
first_laptop = laptop_cards.first
653
first_laptop.click()
654
655
# Combine locators
656
form_inputs = page.locator("form").locator("input")
657
required_inputs = form_inputs.and_(page.locator("[required]"))
658
659
# Fill all required inputs
660
for i in range(required_inputs.count()):
661
input_locator = required_inputs.nth(i)
662
input_locator.fill("test value")
663
664
browser.close()
665
```
666
667
### Complex Element Interaction
668
669
```python
670
with sync_playwright() as p:
671
browser = p.chromium.launch()
672
page = browser.new_page()
673
674
page.goto("https://example.com/app")
675
676
# Multi-step form interaction
677
page.get_by_label("First Name").fill("John")
678
page.get_by_label("Last Name").fill("Doe")
679
680
# Select from dropdown
681
country_select = page.get_by_label("Country")
682
country_select.select_option(label="United States")
683
684
# Check multiple checkboxes
685
interests = ["Technology", "Sports", "Music"]
686
for interest in interests:
687
page.get_by_role("checkbox", name=interest).check()
688
689
# Upload file
690
file_input = page.get_by_label("Profile Picture")
691
file_input.set_input_files("profile.jpg")
692
693
# Submit with confirmation
694
submit_btn = page.get_by_role("button", name="Create Account")
695
696
# Wait for confirmation dialog
697
with page.expect_event("dialog") as dialog_info:
698
submit_btn.click()
699
dialog = dialog_info.value
700
dialog.accept()
701
702
browser.close()
703
```
704
705
### Element State Validation
706
707
```python
708
with sync_playwright() as p:
709
browser = p.chromium.launch()
710
page = browser.new_page()
711
712
page.goto("https://example.com/form")
713
714
# Check initial states
715
submit_btn = page.get_by_role("button", name="Submit")
716
assert submit_btn.is_disabled()
717
718
# Fill required field
719
email_input = page.get_by_label("Email")
720
email_input.fill("test@example.com")
721
722
# Verify button becomes enabled
723
assert submit_btn.is_enabled()
724
725
# Check visibility of elements
726
error_message = page.get_by_text("Email is required")
727
assert error_message.is_hidden()
728
729
# Clear field to trigger validation
730
email_input.clear()
731
assert error_message.is_visible()
732
733
browser.close()
734
```