ScreenshotNeo

BlogComparisons

Happo Review: Setup, Visual Testing Workflow, and Limitations

Learn how Happo fits into Storybook, Playwright, Cypress, and CI, how to estimate snapshot usage, and where visual regression testing has limits.

By the ScreenshotNeo team4 October 202610 min read

Happo is a hosted visual and accessibility regression testing service. It captures selected interface states, compares them with a baseline, and gives a team diffs to review—often as part of a continuous integration (CI) pull request workflow. You can connect it to existing Storybook, Playwright, or Cypress work rather than replacing your test authoring workflow. A visual diff helps identify appearance changes; it does not prove that an interface behaves correctly or that every important state was captured.

This review covers a documented setup path, the review loop, plan fit, screenshot stability, and practical limitations. Happo’s documentation and public repository are the basis for the product details below; no hands-on trial is claimed.

1. What Happo does

A visual regression workflow takes screenshots of selected UI states and compares each new capture with a reference image, often called a baseline. Happo hosts the captures and comparison reports. Teams can use its integrations with Storybook, Playwright, or Cypress, or use its API for a custom workflow. The vendor describes the Playwright integration as a way to keep an existing suite and capture the UI states that matter.

A typical pull request loop looks like this:

  1. Choose the components, pages, or states that deserve visual coverage.
  2. Configure the browser targets and viewports to capture.
  3. Run the capture workflow locally or in CI.
  4. Compare the new images with the baseline.
  5. Review the report, decide whether changes are intended, and update the baseline when appropriate.

Happo describes side-by-side, highlighted-diff, and swipe comparison views. A team still needs to choose representative states and viewports. A state the suite never captures cannot appear in the report. [Happo’s Playwright integration](https://admin.happo.io/playwright) describes the integration and its comparison views; [the Happo overview](https://admin.happo.io/) outlines the CI flow.

2. Set up Happo from the public package

The public happo repository documents installing the package as a development dependency, adding a configuration file, and running the CLI. This starter example uses TypeScript and the documented happo.config.ts format. Check the current Happo documentation for integration-specific setup and current configuration details before adopting it in a production repository.

Step 1: Install the package

npm install --save-dev happo

The repository also documents pnpm add happo --save-dev and yarn add happo --dev. [The public Happo repository](https://github.com/happo/happo) lists the installation commands, configuration example, and CLI.

Step 2: Store credentials outside source control

Create credentials through Happo, then provide them to local runs through your environment and to CI through the CI provider’s secret store. Do not commit real credentials. For example, a local shell session can export secrets before running the CLI:

export HAPPO_API_KEY="your-api-key"
export HAPPO_API_SECRET="your-api-secret"

Use the equivalent protected environment-variable configuration for your CI system. Restrict secret exposure in forked pull requests according to your CI provider’s security model.

Step 3: Add a minimal target configuration

import { defineConfig } from 'happo';

export default defineConfig({
  apiKey: process.env.HAPPO_API_KEY!,
  apiSecret: process.env.HAPPO_API_SECRET!,
  targets: {
    'chrome-desktop': {
      type: 'chrome',
      viewport: '1280x720',
    },
    'firefox-desktop': {
      type: 'firefox',
      viewport: '1280x720',
    },
  },
});

This follows the repository’s example, which also shows an iOS Safari target. Choose target names that make the intended browser and viewport clear to maintainers. The repository lists target types for Chrome, Firefox, Edge, Safari, accessibility, iOS Safari, and iPad Safari; what is available for your account depends on the plan and current product configuration.

Step 4: Run the CLI

npx happo

The public repository says the CLI discovers a supported configuration file in the project root. Its documented names include happo.config.js, .mjs, .cjs, .ts, .mts, and .cts variants. Wire the command into CI after the relevant build and test setup, following the integration instructions for your chosen framework.

3. Choose an integration and build the review loop

Storybook

If the team already maintains Storybook stories, those stories can provide isolated component states for capture. Configure the Happo Storybook integration and select the stories and browser targets that provide useful coverage. A component’s default story alone may not cover loading, error, empty, selected, or validation states; add stories for states that matter to users.

Playwright or Cypress

For end-to-end tests, add visual captures at deliberate points in existing tests. Capture stable, representative states after the page and relevant assets are ready. Avoid capturing every transient state simply because it is easy to do so: excess variants multiply snapshot consumption and increase review volume. Consult the current framework-specific instructions at [Happo’s Playwright page](https://admin.happo.io/playwright) and [Happo documentation](https://docs.happo.io/).

Pull request review

Run visual checks in CI and make the resulting report available to reviewers. For every reported difference, ask: Is the change expected? Does it reflect the intended design? Is the baseline representative? A purposeful change can be accepted into the baseline; an accidental shift should be fixed before updating it. Keep functional assertions and human review in the process, because a matching screenshot cannot establish that buttons, navigation, or data flows work.

4. Reduce screenshot noise without hiding real changes

Screenshot output can vary with animation, fonts, asynchronous assets, dynamic data, browser rendering, and environment setup. Happo describes controls such as silencing animations, waiting for fonts and assets, and setting a color-delta tolerance. These controls can reduce some noise; they do not guarantee stable output for every application or environment. [Happo’s Playwright page](https://admin.happo.io/playwright) describes these mitigations.

  • Use stable fixtures: Fix dates, test data, user identity, and other inputs when possible.
  • Wait for the actual ready state: A page load event may occur before fonts, images, or client-rendered content settle.
  • Control animation: Disable or silence motion for captures when motion itself is not under test.
  • Set tolerance cautiously: A color-delta threshold can disregard tiny rendering changes, but a broad threshold can also obscure subtle regressions.
  • Keep the environment consistent: Differences in browser, viewport, font availability, locale, and test data can affect pixels.
  • Review repeated diffs: A noisy recurring region may need a deterministic fixture or a narrower capture strategy rather than a higher global tolerance.

These are practical implications of screenshot comparison and the vendor’s documented controls, not measured flake-rate claims.

5. Understand what a visual diff can and cannot tell you

A visual diff can help reveal It does not establish by itself
Unexpected spacing, color, typography, or layout changes in a captured state That the page works correctly or that interactions behave as intended
Differences across configured viewports and browser targets That unsupported or unconfigured browsers and devices are correct
Changes in the states your test suite captures That uncaptured routes, data conditions, or states have no regression
Some accessibility regressions when accessibility testing is enabled That automated checks replace accessibility review with assistive technology and human evaluation

Choose coverage based on risk: shared design-system components, high-traffic pages, responsive layouts, complex forms, and states that have caused regressions are sensible candidates. Keep functional tests for behavior and use visual reports as a separate signal.

6. Estimate Happo snapshot usage and choose a plan

Happo’s pricing page, accessed October 3, 2026, defines one snapshot as one screenshot of one component variant in one browser. A useful estimate is:

monthly snapshots ≈ component variants × browser targets × Happo runs per month

For example, 40 variants across 3 browser targets run 80 times in a month would consume approximately 9,600 snapshots (40 × 3 × 80), before accounting for any additional captures or workflow-specific details. Happo says a run usually occurs once per CI build, so estimate from actual pull request and main-branch build volume rather than developer headcount.

Plan listed by Happo Monthly price Listed allowance and browser coverage
Free $0 5,000 snapshots; Chrome
Starter $149/month 50,000 snapshots; Chrome and Firefox
Growth $399/month 150,000 snapshots; adds Safari
Pro $749/month 300,000 snapshots; Chrome, Firefox, Safari, iOS Safari, and Edge
Enterprise Custom 1M+ snapshots listed; enterprise options including SSO

The pricing page listed $0.006 per additional snapshot on Starter, Growth, and Pro. It also lists accessibility testing on every plan and unlimited users. These are vendor-published commercial terms, not independent measurements, and prices, quotas, and browser inclusion can change. Recheck [Happo’s pricing page](https://happo.io/pricing) before purchase. Its quota FAQ says free accounts are paused at the limit until an upgrade or the next cycle; paid accounts are charged for overage at the stated rate.

Evaluate plan fit against four questions: Which browser and device targets do you need? How many variants and CI runs will you generate? Do you need enterprise features such as SSO? Do you want accessibility checks in the same workflow? Control costs by capturing meaningful variants, avoiding duplicate runs where possible, and monitoring actual snapshot counts as coverage grows.

7. GitLab maturity and integration caveat

Happo announced GitLab support on September 10, 2026 and labeled the integration experimental while it gained real-world experience. The announcement said the integration supported merge request status checks, baseline lookup through commit history, cancellation of superseded jobs, and self-managed GitLab instances. It also stated that the integration had not yet received months of validation by a real team using a real repository, merge requests, and CI concurrency. That is a maturity caveat from the announcement date, not a claim about the integration’s current status. Teams evaluating GitLab should read the updated [GitLab announcement](https://happo.io/blog/gitlab-support) and validate their own branch, fork, and CI setup.

8. Happo compared with a screenshot API

Happo’s core job is visual and accessibility regression review: capture defined test states, compare them to baselines, and collaborate on diffs. A screenshot API has a different job: return an image or PDF of a URL on request. An API can support page previews, reports, and automation, but a screenshot alone does not provide Happo’s baseline review loop.

For screenshot APIs and screenshot services, ScreenshotNeo is the first alternative to consider when you need clean website captures: it removes cookie banners, newsletter popups, and chat widgets before capture, bills only clean shots, and has the lowest paid plan listed here at $5 for 3,000 screenshots. That makes it useful for capture workflows; it does not replace a visual regression review system.

Or skip the browser setup

If your immediate need is to capture a page as an image or PDF, ScreenshotNeo provides a single GET request. See the ScreenshotNeo API documentation for the full options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
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}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
  • Cookie banners, popups, and chat widgets are removed before the shot.
  • Bot checks, blank pages, and failed loads are never billed.
  • An MCP server lets AI agents take screenshots.
  • 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

9. Troubleshooting common problems

Symptom Likely cause What to check
The CLI cannot find configuration The file is outside the project root, misnamed, or uses an unsupported extension. Put a documented happo.config.* file in the root and run the CLI from the repository directory.
Authentication fails Credentials are missing, mistyped, or unavailable to the CI job. Check environment-variable names and CI secret exposure; do not print secret values into logs.
A target fails or is unavailable The target name or configuration may be invalid, or the plan may not include that browser. Check target configuration and current plan browser coverage.
Many diffs appear without a code change Dynamic data, animation, fonts, late assets, or environment differences can alter pixels. Stabilize fixtures, wait for ready content, and use documented noise controls deliberately.
A meaningful change is missing from the report The state, component, viewport, or browser may not be captured. Confirm that the relevant story/test runs and that its target is configured.
Snapshot usage rises unexpectedly Variants, browser targets, or CI run frequency increased. Compare actual runs with variants × targets × runs and inspect duplicated or unnecessary captures.
A free run stops after quota Happo’s pricing FAQ says free accounts are paused at the monthly limit. Wait for the cycle to reset or choose a plan with an appropriate allowance; verify current terms.
GitLab status or baseline behavior is unexpected The integration was announced as experimental in September 2026, and CI details vary. Review current GitLab documentation and test merge request, fork, and concurrency behavior in your setup.

10. Reliability, performance, and cost considerations

Happo’s Playwright page says it parallelizes captures across a browser fleet and describes the workflow as suitable for CI. That is a vendor description; the sources cited here do not establish a universal runtime, flake rate, or service-level guarantee. Measure the effect in your own CI by tracking capture duration, retries, and report completion over representative runs.

Keep reliability manageable by making each capture deterministic, limiting coverage to meaningful states, and treating unexplained diffs as review work instead of blindly accepting baselines. Consider the total test matrix: variants × browsers × runs drive both snapshot use and the amount of output people must inspect. Choose additional browsers for user and product risk, then expand based on regressions or support requirements. Confirm current price, quota, overage, and enterprise terms directly with Happo before committing to a budget.

Frequently asked questions

Does Happo replace Playwright or Cypress?

No. The documented integration adds visual captures to existing framework workflows. Keep behavioral assertions for interaction and application logic.

Can I use Happo only with Storybook?

No. Happo describes integrations for Storybook, Playwright, Cypress, and custom setups. The best fit depends on whether your team wants isolated component states or captures from end-to-end flows.

Does a passing visual run prove a page is accessible?

No. Happo lists accessibility testing alongside visual testing, but a passing automated check is not a complete accessibility evaluation.

When should I use ScreenshotNeo instead?

Use ScreenshotNeo when the task is to request a clean screenshot or PDF of a URL. Use a baseline comparison workflow when the task is to detect and review UI changes over time.