Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Cypress’s bundled Chai assertions to check JavaScript objects and API responses against the contract your application depends on. For an API response, call cy.request(), inspect its body, and assert the required status, properties, types, values, and nested structure. Use exact-key or deep-equality assertions only when extra or changed data should genuinely fail the test.
Choose an assertion that matches the contract
Cypress includes Chai assertions, so you can use familiar expect(...) assertions or Cypress chains such as .should(...). The important choice is not syntax alone: decide whether the test protects an exact object shape or only the fields the application consumes. Cypress documents its assertion library and supported styles in its Assertions in Cypress reference.
| What you need to guarantee | Useful style | Trade-off |
|---|---|---|
| A property has a particular value | expect(value).to.eq(expected) or .should('eq', expected) |
Focused and readable; does not validate unrelated fields. |
| An object contains required keys | expect(object).to.include.all.keys(...) |
Allows additional keys, which is useful when the API can add fields without affecting the consumer. |
| An object has exactly the listed keys | expect(object).to.have.all.keys(...) |
Fails if a key is added or removed; use only when the exact shape is part of the contract. |
| An object equals a known object, including nested values | expect(actual).to.deep.eq(expected) |
Strict and concise for stable, intentionally fixed data; can be brittle for responses with irrelevant fields. |
| A value has a type or falls within a set or range | .to.be.a('number'), .to.be.oneOf([...]), or .to.be.greaterThan(...) |
Checks a constraint without requiring one specific value. |
Prefer assertions that express what a consumer needs. For example, if a client needs id, total, and currency, asserting those fields can be more resilient than rejecting every harmless server-side addition. Conversely, if an extra property would signal a security or compatibility problem, explicitly assert the exact key set.
Outdated 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 matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Validate an API response with cy.request()
cy.request() makes an HTTP request and yields a response containing its status, body, headers, and duration. Cypress parses the response body as a JavaScript object when the response Content-Type ends in json; otherwise the body is a string. Cypress’s API testing guide and cy.request() reference describe the command and response behavior.
#1 Best Overall
Here is a complete test of a cart response, checking the contract at several levels:
describe('GET /cart', () => {
it('returns a cart the checkout client can use', () => {
cy.request('/cart').then((response) => {
expect(response.status).to.eq(200)
const cart = response.body
expect(cart).to.have.all.keys(
'id', 'items', 'subtotal', 'tax', 'total', 'currency'
)
expect(cart.id).to.be.a('string').and.not.be.empty
expect(cart.items).to.be.an('array')
expect(cart.currency).to.be.oneOf(['USD', 'EUR', 'GBP'])
expect(cart.subtotal).to.be.a('number')
expect(cart.tax).to.be.a('number')
expect(cart.total).to.be.a('number')
cart.items.forEach((item) => {
expect(item).to.include.all.keys('sku', 'quantity', 'unitPrice')
expect(item.sku).to.be.a('string').and.not.be.empty
expect(item.quantity).to.be.a('number').and.greaterThan(0)
expect(item.unitPrice).to.be.a('number')
})
})
})
})
The exact cart fields and allowed currencies here are illustrative: use the contract of the API under test. The example deliberately requires an exact top-level key set but only required keys on each item. Remove exactness if new top-level fields are allowed, or add value constraints only where the application depends on them. An assertion that a value is a number does not, by itself, guarantee that it is finite, non-negative, or in an expected range; express those requirements separately when they matter.
Check a single property
For a straightforward property assertion, the chain can be shorter:
cy.request('/users/1')
.its('body.username')
.should('eq', 'jdoe')
This reads well when a test is about one field. For a complete response contract, access the response in .then() and group the related assertions there.
Compare nested data with deep equality
When the expected object is intentionally exact, use a deep comparison:
Rank #2
cy.request('/users/1')
.its('body')
.should('deep.eq', { name: 'Jane' })
Deep equality compares nested values rather than checking whether two object references are identical. Keep expected objects small and stable; a full comparison of a response containing timestamps, generated identifiers, or unrelated fields can make a test noisy and fragile.
Test validation errors intentionally
By default, a non-success response can cause cy.request() to fail the command. When the purpose of the test is to verify an error response, set failOnStatusCode: false so the test can inspect it:
Free tools Windows power users keep installed
One-click scans. No signup required.
it('rejects an order without line items', () => {
cy.request({
method: 'POST',
url: '/orders',
body: { lineItems: [] },
failOnStatusCode: false,
}).then((response) => {
expect(response.status).to.eq(422)
expect(response.body.errors).to.deep.include({
field: 'lineItems',
message: 'must contain at least one item',
})
})
})
The 422 status and error shape are examples, not universal rules. Assert the status code and error payload that your service promises. Use a partial deep inclusion when an error array may contain additional entries; use exact equality only if the full error collection is contractually fixed.
Understand retries before choosing should() or then()
Use .should() when Cypress can retry the subject while waiting for a condition to become true, particularly for asynchronously changing UI state. A .should(callback) callback groups assertions, and Cypress retries that assertion block while the subject remains retryable. Keep callbacks free of side effects because Cypress may run them more than once. See the Cypress introduction for retry behavior.
Use .then() for ordinary synchronous assertions on a resolved response. A cy.request() has already completed when its response is yielded: assertions chained from that request run once. Do not expect a failed body assertion to repeat the HTTP request. Request options for retrying eligible network or status failures are separate from Cypress’s assertion retry mechanism; configure them deliberately according to the request API reference rather than treating them as assertion retries.
For example, this is appropriate for a response that has arrived:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
cy.request('/users/1').then((response) => {
expect(response.status).to.eq(200)
expect(response.body.active).to.eq(true)
})
A UI value that appears after an asynchronous update is a different case; assert against the retryable Cypress subject instead of capturing a one-time value and expecting Chai to poll it.
Use fixtures for reusable test data
Keep a small, case-specific expected value inline when that makes the test easier to understand beside its assertions. Put substantial or shared test data in a fixture. Cypress’s cy.fixture() API reference covers fixture loading and the supported fixture formats.
it('checks a user fixture', () => {
cy.fixture('user.json').then((user) => {
expect(user).to.include.all.keys('id', 'username', 'active')
expect(user.username).to.be.a('string')
expect(user.active).to.be.a('boolean')
})
})
Make the fixture’s format and the assertion agree: a JSON fixture supplies parsed data, while other formats may yield text or another representation. Do not use a fixture merely to move a tiny, one-off expected value away from the test that explains it.
Avoid assertions that pass for the wrong reason
A negative assertion can be technically true while the application is broken in a different way. For example, asserting that a list does not contain a particular item does not establish that the right items remain: the application might have deleted everything or inserted a blank item. Cypress’s assertions reference discusses this weakness with list-count examples. Assert the resulting expected value, shape, or count directly.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsRank #4
- Instead of only asserting that a bad value is absent, assert that the required valid values are present.
- Instead of only asserting that a list count is not a particular number, assert the intended count or expected list content.
- Instead of checking only that a response field exists, check its type and any range or format the consumer requires.
- Use exact-key assertions only where rejecting additional fields is intentional; otherwise assert required keys.
Troubleshoot common data-validation failures
The response body is a string, not an object
Cypress yields a string when the response content type does not end in json. Inspect response.headers and the server’s response headers; correct the API content type or explicitly parse the text if that is the documented response format. Avoid assuming response.body.someProperty is valid for every endpoint.
A request fails before the error body can be checked
For a test that expects a non-success status, add failOnStatusCode: false to the request options, then assert the expected status and response structure. Without that setting, default request behavior treats an unsuccessful response as a command failure.
An exact-key assertion breaks after an API change
Determine whether the extra or changed key violates a consumer-facing contract. If it is a harmless addition, change the test to assert that required keys are included rather than asserting that all keys are exactly equal. Keep exactness when the consumer or compatibility requirements depend on it.
A should() assertion is not waiting for an API response
Assertions on a completed cy.request() response are not automatically retried. A retryable .should() is useful for supported Cypress subjects such as changing UI state; it does not turn a completed HTTP request into a polling loop. If the application requires polling, implement that behavior explicitly rather than relying on an assertion to resend the request.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →A negative assertion passes despite broken data
Replace it with a direct assertion of the desired result: an expected item, a precise count, or a required object shape. Negative checks are useful only when absence itself is the meaningful contract and the test also rules out incorrect alternate outcomes.
Best Value
Or skip the browser setup
Screenshot capture is separate from Cypress data assertions: ScreenshotNeo does not replace a test of an API object’s shape or values. If a separate part of your workflow needs a website screenshot, its API can capture a URL without setting up a browser automation script. The ScreenshotNeo website describes its screenshot API and MCP server.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for request details. It removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Its MCP server provides screenshot tools for AI agents. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo’s free plan to try screenshot capture with 1,000 shots a month and no card.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Frequently Asked Questions
Can Cypress validate a JavaScript object that was not returned by an API?
Yes. Pass the object directly to Chai’s expect() assertions, or assert against a Cypress subject that yields that object; the same property, key, type, and equality checks apply.
Does cy.request() test the application through the browser UI?
No. It makes an HTTP request directly and yields the response. Use a browser-interaction test when the behavior you need to verify depends on the rendered interface or user actions.
Should every API response test assert every field?
No. Assert the fields and constraints that protect the consumer-facing contract; require an exact key set only when additional fields should be considered a failure.
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.

