How to use Percy with Cypress in an Angular project
Add Percy visual snapshots to Cypress end-to-end or Angular component tests. Install the SDK, configure your token, capture stable UI states, and troubleshoot common issues.
To use Percy with Cypress in an Angular project, install @percy/cli and @percy/cypress, import the Cypress SDK from the support file your project uses, and call cy.percySnapshot() after the page reaches a stable state. Set your Percy project token as PERCY_TOKEN and run the suite through npx percy exec -- cypress run. The same Percy integration can be used with Cypress end-to-end tests and component tests; Angular component-test setup has separate version and build-tool requirements.
1. Check your Cypress test type and project setup
First identify whether the tests are end-to-end (E2E) or Angular component tests. Percy adds visual snapshots to Cypress; it does not configure Angular’s component-test dev server or bundler.
| Test type | What Cypress runs | What to check |
|---|---|---|
| End-to-end | The Angular application in a browser, usually through a local or deployed URL. | Your existing Cypress E2E configuration, base URL, and support file. |
| Component | An Angular component mounted in Cypress’s component-testing harness. | Cypress’s currently documented Angular support and the component dev-server configuration. |
Cypress currently documents Angular component testing for Angular ^21.0.0 and ^22.0.0. The cypress/angular harness requires @angular-devkit/build-angular, including projects built with @angular/build. Cypress 16 supports zoneless component testing without additional configuration; Angular 21 and 22 use zoneless by default. These are component-testing details, not general requirements for E2E tests. See the Cypress Angular Component Testing documentation.
2. Install Percy’s Cypress SDK and CLI
From the Angular project root, install both development dependencies:
npm install --save-dev @percy/cli @percy/cypress
Use the support entrypoint configured for your Cypress project. Current Cypress projects commonly use cypress/support/e2e.js for E2E tests; the Percy package README also shows cypress/support/index.js. The important part is that Cypress loads the import from the support file for the test type you run.
// cypress/support/e2e.js
import '@percy/cypress'
If your project uses TypeScript, add Percy’s types alongside Cypress’s in the relevant tsconfig.json:
{
"compilerOptions": {
"types": ["cypress", "@percy/cypress"]
}
}
Keep any other existing type entries in that array. For component tests, make sure the component support file also loads the SDK if snapshots are called from component specs. The Percy Cypress integration guide documents this setup for SDK version 3.0.0 and above.
3. Create a Percy project and provide its token
Create a Percy Web project and provide its project token to the process that runs Cypress. Use your CI system’s secret/environment-variable settings for CI, and a local untracked environment file or shell environment for local runs. Do not commit the token to source control.
# macOS/Linux shell
export PERCY_TOKEN="your-project-token"
npx percy exec -- cypress run
For a one-off local command, set the variable inline:
PERCY_TOKEN="your-project-token" npx percy exec -- cypress run
In CI, configure PERCY_TOKEN as a secret, then use the same run command. The token must be available to the Percy CLI process that wraps Cypress.
4. Add snapshots after the Angular UI is ready
Place cy.percySnapshot() after Cypress has navigated to the page, established the state you want to protect, and checked that the relevant content is ready. For example:
// cypress/e2e/home.cy.js
describe('Angular home page visual states', () => {
it('captures the ready state', () => {
cy.visit('/')
cy.get('[data-testid="ready"]').should('be.visible')
cy.percySnapshot('Home page — ready')
})
})
Use snapshot names that are unique within the build when you specify them. Useful targets include a completed form, open navigation, dialog, loaded data view, and important success or error states. Cypress assertions make the intended state explicit; avoid capturing while data is still loading or an animation is mid-frame.
Percy’s Cypress integration captures DOM snapshots through cy.percySnapshot() and renders them for comparison in Percy. Cypress’s own cy.screenshot() captures an image but does not perform image comparison. The review cycle is capture, compare with a baseline, inspect differences, then approve intentional changes or fix regressions. A visual difference needs review; by itself, it does not prove application behavior is broken. See Cypress Visual Testing documentation.
5. Configure snapshot widths and comparison behavior
Percy’s integration guide demonstrates supplying responsive widths to a snapshot. For example:
cy.percySnapshot('Home page responsive', {
widths: [768, 992, 1200]
})
Choose widths that correspond to layouts your team wants to review. More widths mean more rendered variations to inspect. Percy compares against a base build; the integration guide says the default is the previous Percy build, and teams can configure the base build. Confirm the base-build choice in your project’s Percy settings and CI workflow so comparisons use the intended reference.
Keep visual inputs repeatable where practical: use stable test data, control time-dependent content, wait for the page’s meaningful ready condition, and keep the rendering setup consistent. Third-party content, randomized values, clocks, and asynchronous loading can cause noisy differences.
6. Angular component testing configuration
If you are adding Percy to Angular component tests, configure Cypress’s component dev server independently of Percy. Cypress documents this configuration shape:
// cypress.config.ts
import { defineConfig } from 'cypress'
export default defineConfig({
component: {
devServer: {
framework: 'angular',
bundler: 'webpack',
},
specPattern: '**/*.cy.ts',
},
})
Angular CLI projects are automatically detected during Cypress component-testing setup. If you provide a custom Angular projectConfig, Cypress warns that it replaces detected settings. Required build options such as styles and Sass include paths may then need to be repeated. Check the actual angular.json and Cypress configuration if component compilation or styling fails. This component-test configuration is not needed just to add Percy to E2E tests.
7. Run locally and in CI
- Install the two development dependencies.
- Import
@percy/cypressfrom the support file used by the target test type. - Add snapshots after stable, asserted UI states.
- Set the Percy project token in the environment.
- Run
npx percy exec -- cypress run. - Review the resulting Percy build, inspect diffs, and approve intentional visual changes or correct regressions.
When diagnosing an integration issue, run one targeted spec first. Once the command, token, support import, and snapshot are working together, run the full suite in CI.
8. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Snapshots are disabled or no Percy build is produced. | Cypress was started directly rather than through Percy, or PERCY_TOKEN is missing from the wrapped process. |
Run npx percy exec -- cypress run and verify the token is present in that shell or CI job. |
cy.percySnapshot is undefined. |
The SDK is not imported by the support file loaded for this test type, or the package is absent. | Install @percy/cypress, check the configured E2E or component support file, and import the SDK there. |
TypeScript reports that percySnapshot does not exist. |
Percy’s Cypress types are not included in the test TypeScript configuration. | Add "@percy/cypress" to the types array with "cypress", then confirm the package is installed and imported. |
| The visual diff changes between runs without a code change. | The page may contain time-dependent, randomized, animated, or asynchronously loaded content, or the test captures before the UI is stable. | Use deterministic fixtures, assert readiness, and avoid capturing during transitions. Review whether external content is changing. |
| Angular component compilation fails before Percy runs. | The component-testing harness, Angular version, build dependency, or custom project configuration may be incompatible or incomplete. | Check the documented Angular version support, install @angular-devkit/build-angular, inspect angular.json, and restore needed styles or Sass include paths in custom configuration. |
| Styles are missing in component snapshots. | A custom projectConfig replaced detected Angular settings, including style configuration. |
Copy the required styles and build options from the project’s Angular configuration into the custom Cypress component setup. |
| An upgraded project still configures a Percy task. | The project may retain the legacy Percy Cypress 2.x health-check task. | For the 3.x CLI toolchain, remove the old @percy/cypress/task health-check task and ensure scripts use @percy/cli. |
| Every visual build shows a large number of changes. | The selected base build may not be the intended baseline, or the rendering inputs/environment changed. | Check Percy’s base-build configuration, test data, responsive widths, and rendering consistency before approving changes. |
Percy Cypress SDK setup and Angular’s Cypress component harness are separate layers. If an Angular test fails before Cypress reaches the snapshot command, resolve the Cypress/Angular test setup first.
9. Performance, reliability, and cost considerations
- Runtime: each snapshot and responsive width adds visual work and review output. Capture states that protect meaningful user journeys rather than taking redundant snapshots after every minor interaction.
- Reliability: assert the state you intend to compare, keep data stable, and avoid timing-only waits when a selector or application-ready condition is available. Treat a diff as a signal for human review.
- Coverage: Cypress’s visual-testing overview distinguishes local image-comparison approaches from hosted comparison and review workflows. Compare tools by subscription versus self-hosting, where rendering and comparison happen, baseline management, browser and viewport coverage, and review workflow. The dossier does not establish current Percy prices or plan limits, so check the vendor’s current terms before budgeting.
- Scope: visual comparison complements functional and accessibility checks; it does not establish that behavior works or that a page is accessible.
10. Or skip the browser setup
If you need a screenshot of a URL without wiring a browser into this workflow, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF. Its API can remove cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are not billed; and its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. It is a URL screenshot service, not a Percy visual-baseline comparison workflow.
See the ScreenshotNeo API documentation. cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' })
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`)
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`)
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())))
Sign up free for 1,000 screenshots a month, with no card required.
11. Frequently asked questions
Does Percy replace Cypress assertions?
No. Cypress assertions check behavior and state; Percy captures visual states for comparison. Use both for their respective jobs.
Can I use the same Percy snapshot approach for E2E and component tests?
The snapshot command is part of the Cypress SDK, but each test type has its own support file and setup. Component tests also need a supported Angular/Cypress component harness.
Do I need to take a Cypress screenshot before calling Percy?
No. Call cy.percySnapshot() at the desired point in the test. Cypress’s cy.screenshot() is a separate screenshot-capture command.
What should I do with an unexpected diff?
Inspect the changed region and the build’s baseline. Fix unintended UI changes; approve changes only when they are expected.


