get
Get one or more DOM elements by selector or alias.
The querying behavior of this command is similar to how
$(...) works in jQuery.
Syntax​
cy.get(selector)
cy.get(alias)
cy.get(selector, options)
cy.get(alias, options)
Usage​
Correct Usage
cy.get('.list > li') // Yield the <li>'s in .list
Arguments​
selector (String selector)
A selector used to filter matching DOM elements.
alias (String)
An alias as defined using the .as() command and referenced
with the @ character and the name of the alias.
You can use cy.get() for aliases of DOM elements, primitives, objects,
intercepts, spies, and stubs.
By default, an alias re-runs the queries leading up to it each time you request
it, so an aliased DOM element reflects the current state of the page. An alias
created with { type: 'static' } yields the value captured when the alias was
created. See .as() for details.
options (Object)
Pass in an options object to change the default behavior of cy.get().
| Option | Default | Description |
|---|---|---|
log | true | Displays the command in the Command log |
timeout | defaultCommandTimeout | Time, in milliseconds, to wait for cy.get() to resolve before timing out. Must be a number. |
withinSubject | the .within() subject, otherwise the document | Element to search within. Pass null to search from the document. |
includeShadowDom | includeShadowDom config option value | Whether to traverse shadow DOM boundaries and include elements within the shadow DOM in the yielded results. |
Yields ​
cy.get()yields the DOM element(s) it found, or the results of the alias lookup.- For an intercept alias,
cy.get()yields the most recent interception, ornullif no request has matched yet. cy.get()is a query, and it is safe to chain further commands.
Examples​
Selector​
Get the input element​
cy.get('input').should('be.disabled')
Find the first li descendant within a ul​
cy.get('ul li:first').should('have.class', 'active')
Find the first li in every ul​
:first is a jQuery extension that yields only the first matching element on
the whole page. To get the first li in each list, use the CSS :first-child
selector instead.
<ul class="fruits">
<li>Apple</li>
<li>Banana</li>
</ul>
<ul class="vegetables">
<li>Carrot</li>
<li>Pea</li>
</ul>
cy.get('ul li:first').should('have.length', 1) // Apple only
cy.get('ul li:first-child').should('have.length', 2) // Apple and Carrot
Find the dropdown-menu and click it​
cy.get('.dropdown-menu').click()
Find 5 elements with the given data attribute​
Dedicated data-* attributes such as data-cy keep selectors stable when your
styles or text change. See
best practices for selecting elements.
cy.get('[data-cy=todo-item]').should('have.length', 5)
Find the first or nth element with .first() and .eq()​
Chaining .first() or .eq() onto
cy.get() reads more clearly than a :first or :eq() selector.
cy.get('[data-cy=todo-item]').first().should('contain', 'Buy milk')
cy.get('[data-cy=todo-item]').eq(1).should('contain', 'Walk dog')
Find elements matching any of several selectors​
Separate selectors with commas to yield every element that matches any of them.
cy.get('input, textarea, select').should('have.length', 3)
Find the link with an href attribute containing the word "questions" and click it​
cy.get('a[href*="questions"]').click()
Find the element with id that starts with "local-"​
cy.get('[id^=local-]')
Find the element with id that ends with "-remote"​
cy.get('[id$=-remote]')
Find the element with id that starts with "local-" and ends with "-remote"​
cy.get('[id^=local-][id$=-remote]')
Find the element with id that has characters used in CSS like ".", ":"​
cy.get('#id\\.\\.\\.1234') // escape the character with \\
Find an element by an ID built at runtime​
When the ID comes from a variable, escape it with
CSS.escape()
instead of adding backslashes by hand.
const userId = 'user:42'
cy.get(`#${CSS.escape(userId)}`).should('have.text', 'Jane')
cy.get() in the .within() command​
Since cy.get() is chained off of cy, it always looks for the selector within
the entire document. The only exception is when used inside a
.within() command.
cy.get('form').within(() => {
cy.get('input').type('Pamela') // Only yield inputs within form
cy.get('textarea').type('is a developer') // Only yield textareas within form
})
Get vs Find​
The cy.get command always starts its search from the
cy.root element. In most cases, it is the
document element, unless used inside the .within()
command. The .find command starts its search from
the current subject.
<div class="test-title">cy.get vs .find</div>
<section id="comparison">
<div class="feature">Both are querying commands</div>
</section>
cy.get('#comparison')
.get('div')
// finds the div.test-title outside the #comparison
// and the div.feature inside
.should('have.class', 'test-title')
.and('have.class', 'feature')
cy.get('#comparison')
.find('div')
// the search is limited to the tree at #comparison element
// so it finds div.feature only
.should('have.length', 1)
.and('have.class', 'feature')
Waiting for elements​
Wait for a list to finish loading​
cy.get() retries until the assertion chained to it passes, so it waits for
all three items to appear.
cy.get('[data-cy=todo-item]').should('have.length', 3)
An assertion inside .then() runs only once. cy.get()
waits only until at least one item exists, so this fails if the list is still
filling in:
// Runs once: fails if the list is still loading
cy.get('[data-cy=todo-item]').then(($items) => {
expect($items).to.have.length(3)
})
Assert an element doesn't exist​
cy.get() retries a negative assertion too, until the element is gone.
cy.get('[data-cy=loading-spinner]').should('not.exist')
Options​
Wait longer for a slow element with timeout​
cy.get('[data-cy=search-results]', { timeout: 10000 }).should('be.visible')
Find elements inside shadow DOM with includeShadowDom​
cy.get('.shadow-button', { includeShadowDom: true }).click()
To search shadow DOM in every query, set the
includeShadowDom configuration option
instead.
Hide a query from the Command Log with log​
The get row is hidden, but the assertion still appears in the Command Log.
cy.get('[data-cy=toast]', { log: false }).should('be.visible')
Alias​
For a detailed explanation of aliasing, read more about aliasing here.
Get the aliased 'todos' elements​
cy.get('ul#todos').as('todos')
//...hack hack hack...
//later retrieve the todos
cy.get('@todos')
Get the aliased 'submitBtn' element​
beforeEach(() => {
cy.get('button[type=submit]').as('submitBtn')
})
it('disables on click', () => {
cy.get('@submitBtn').click()
cy.get('@submitBtn').should('be.disabled')
})
Get the aliased 'users' fixture​
beforeEach(() => {
cy.fixture('users.json').as('users')
})
it('shows the first user in the header', () => {
// access the array of users
cy.get('@users').then((users) => {
// get the first user
const user = users[0]
cy.get('header').contains(user.name)
})
})
Re-run an alias or capture a static value​
By default, an alias re-runs its queries each time you request it. Pass
{ type: 'static' } to .as() to keep the value from the
moment you created the alias.
cy.get('[data-cy=total]').invoke('text').as('liveTotal')
cy.get('[data-cy=total]').invoke('text').as('startTotal', { type: 'static' })
cy.get('[data-cy=add-item]').click()
cy.get('@liveTotal').should('eq', '$5.00') // re-runs the queries
cy.get('@startTotal').should('eq', '$0.00') // value captured earlier
In the Command Log, the static alias is labeled (static) where it's created:

Assert an aliased element no longer exists​
Because the alias re-runs its query, you can assert that the element is gone.
cy.get('[data-cy=toast]').as('toast')
cy.get('[data-cy=dismiss]').click()
cy.get('@toast').should('not.exist')
Get an aliased spy or stub​
cy.window().then((win) => {
cy.spy(win.console, 'error').as('consoleError')
})
cy.get('[data-cy=save]').click()
cy.get('@consoleError').should('not.have.been.called')
Get all aliased intercepts​
When using cy.intercept() with an alias, you can
retrieve all intercepted requests for that alias by appending .all to the
alias name. This returns an array of
interception objects.
cy.intercept('GET', '/users').as('getUsers')
// trigger multiple requests
cy.visit('/users')
cy.visit('/users')
// yields an array of all interceptions for this alias
cy.get('@getUsers.all').then((interceptions) => {
expect(interceptions).to.have.length(2)
})
You can also retrieve a specific intercept by its 1-based numeric index. Without
any suffix, cy.get('@alias') returns the most recent intercepted request.
cy.intercept('GET', '/users').as('getUsers')
cy.visit('/users')
cy.visit('/users')
// yields the first intercepted request
cy.get('@getUsers.1').its('response.statusCode').should('eq', 200)
// yields the second intercepted request
cy.get('@getUsers.2').its('response.statusCode').should('eq', 200)
Index 0 is not valid — indices start at 1. These suffixes are not
supported by cy.wait(). Use cy.get('@alias.all')
instead of cy.wait('@alias.all').
TypeScript​
Type the yielded element or an aliased value​
Pass a type argument to type what cy.get() yields. For a selector, it's the
element type. For an alias, it's the type of the aliased value.
cy.get<HTMLInputElement>('[data-cy=email]').then(($input) => {
// $input is typed as JQuery<HTMLInputElement>
})
cy.wrap({ name: 'Jane' }).as('user')
cy.get<{ name: string }>('@user').its('name').should('eq', 'Jane')
Notes​
What a cy.get() timeout error looks like​
When no element matches before the timeout, cy.get() fails with an error like
this one. The time in the message is the command's timeout:
defaultCommandTimeout, or the
timeout option when you pass one.
Timed out retrying after 4000ms: Expected to find element: `[data-cy=todo-item]`, but never found it.
cy.get() doesn't search inside iframes​
cy.get() searches the document of the application under test and doesn't
descend into <iframe> elements. To query inside a same-origin iframe, see
How do I test elements inside an iframe?.
Rules​
Requirements ​
cy.get()is chained off ofcy. When chained off another command, it ignores that command's subject.
Assertions ​
cy.get()automatically retries until the element(s) exist in the DOM.cy.get()automatically retries until all chained assertions have passed.
Timeouts ​
cy.get()can time out waiting for the element(s) to exist in the DOM.cy.get()can time out waiting for assertions you've added to pass.
Command Log​
Get an input and assert on the value
cy.get('input[name="firstName"]').should('have.value', 'Homer')
The commands above will display in the Command Log as:

When clicking on the get command within the command log, the console outputs
the following:

History​
| Version | Changes |
|---|---|
| 15.17.0 | @-prefixed aliases are typed as Chainable<S> instead of Chainable<JQuery<HTMLElement>> |
| 12.0.0 | Aliases re-run the queries leading up to them by default |
| 5.2.0 | Added includeShadowDom option |