How to Capture Multiple Browsers and Viewports with Happo
Configure Happo targets to compare the same UI across browsers and viewport sizes, then run the captures in CI and review the diffs.
To capture the same UI in multiple browsers and viewport sizes with Happo, define a set of targets in Happo’s configuration. A target represents a browser and its viewport; the integration captures your Storybook stories or test states against each configured target. Run Happo in CI and review the resulting comparisons to catch responsive and browser-specific regressions.
Choose the integration that matches your project: Storybook for component stories, Cypress or Playwright when you want to capture states from existing tests, or Happo’s API for a custom integration. Happo’s current browser options include Chrome, Firefox, Safari, Microsoft Edge, and iOS Safari. Which browsers are available depends on your plan. Check the current Happo pricing page before planning coverage.
1. Choose what to capture
Start with the UI states that matter. A screenshot of one component variant in one browser is one Happo snapshot. If you capture 40 variants in three targets, that is 120 snapshots in a run. Include important states such as loading, error, expanded menus, and responsive navigation; capturing every theoretical combination can make reports noisy.
- Storybook: use stories for reusable components and their meaningful variants.
- Cypress or Playwright: use your existing tests to reach important application states, then add Happo captures at those points.
- Custom integration: use the API when your capture workflow does not fit those integrations.
See Happo’s Storybook, Cypress, and Playwright integration pages for their setup instructions.
2. Define browser and viewport targets
Targets are the coverage matrix. Add a target for each browser and viewport combination you want compared. The example below uses the current configuration shape shown in Happo’s documentation and vendor examples: a named target, a browser type, and a viewport string such as 1024x768.
// happo.config.ts
import { defineConfig } from 'happo';
export default defineConfig({
targets: {
'chrome-desktop': {
type: 'chrome',
viewport: '1440x900',
},
'chrome-mobile-width': {
type: 'chrome',
viewport: '390x844',
},
'firefox-desktop': {
type: 'firefox',
viewport: '1440x900',
},
'safari-tablet-width': {
type: 'safari',
viewport: '768x1024',
},
},
});
Use a distinct target name for each combination. The viewport string is width by height in CSS pixels. Keep the configuration syntax aligned with your installed Happo package version; consult the Happo configuration reference if your project uses an older config format or a different target type.
Pick useful widths
Choose widths around actual layout changes in your design system, not just device marketing categories. If navigation collapses at 768px, capture just above and below that breakpoint. A pair like 767px and 768px can reveal breakpoint mistakes more directly than arbitrary “phone” and “tablet” sizes. Use representative heights too when vertical overflow or sticky elements matter.
Keep the matrix intentional
| Coverage dimension | How to choose it | Common mistake |
|---|---|---|
| Browser | Prioritize engines and platforms used by your customers; verify plan availability. | Adding every browser when the UI states are already redundant. |
| Viewport | Cover breakpoints and layouts that materially differ. | Capturing many nearby widths with no distinct behavior. |
| State | Capture user-visible states with meaningful differences. | Capturing unstable data or states nobody relies on. |
| Run frequency | Run PR checks and baseline updates in your existing CI flow. | Multiplying every variant by every target on every job without estimating usage. |
3. Connect the targets to your integration
For Storybook, configure the Happo Storybook integration so it renders stories against the configured targets. For Cypress or Playwright, install the corresponding Happo integration and add captures after your test has reached the intended state. Follow the integration’s version-specific setup rather than copying a test hook from another package version; these integrations have their own installation and command steps.
For example, your test workflow should conceptually do the following:
- Load the page or component.
- Wait for application data and assets required for the state.
- Perform interactions such as opening a menu or selecting a tab.
- Ask the Happo integration to capture that state.
- Run the Happo command in CI and publish or inspect the comparison report.
Happo describes its integrations as silencing animations and waiting for asynchronous assets and fonts to reduce capture flakiness. Your application still needs deterministic content: freeze clocks where relevant, seed test data, and avoid depending on live third-party content.
4. Run in CI and review the report
Run captures in pull-request CI so reviewers can compare the proposed UI against the baseline. A successful capture job only means screenshots were produced; it does not mean every viewport is visually correct. Inspect changed images and use the report’s side-by-side, diff, or swipe views to distinguish intended changes from regressions.
Keep baseline updates deliberate. When a change is expected, review the full set of affected targets before accepting it. A shared component change can alter many stories, and a change that looks right at desktop width can still break a narrow layout.
5. Estimate snapshot usage before expanding coverage
Use this estimate for a full run:
variants × targets × runs per month = approximate snapshots per month
If you have 40 variants, 4 targets, and 80 CI runs in a month, the estimate is 12,800 snapshots. A target is one browser-and-viewport combination, and each variant captured in that target contributes a snapshot. Happo’s pricing page describes one snapshot as one component variant in one browser; check current plan quotas and included browsers because pricing and availability can change.
To keep usage and review time under control, prioritize high-risk stories, avoid duplicate widths that exercise the same layout, and use the integration’s supported filtering or partial-run features when appropriate. Don’t remove a browser that serves important users just to shrink the matrix without first considering the risk.
Reliability and performance
- External assets: remote images, fonts, analytics, and ads can change independently and make captures flaky. Happo’s hostname allowlist option can restrict worker requests. Roll it out by checking which requests are blocked, then allow only hosts needed for the snapshots. The allowlist is off by default according to Happo’s September 2026 post.
- Fonts and images: wait for required fonts and content to load. A fallback font or late image changes geometry and creates misleading diffs.
- Animations: disable or stabilize transitions and animated content so the capture does not depend on timing.
- Target count: more targets mean more captures and generally more work. Add targets incrementally, then monitor CI duration and snapshot use.
- Network access: if a page relies on a host that is blocked, the screenshot may show missing content. Inspect worker logs and allow the required hostname rather than opening access broadly.
Happo’s vendor blog reports one customer saw flaky variants fall from roughly 2,000 to roughly 20 after restricting worker requests. That is a vendor-reported customer example, not a general expected result.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| A target is missing from the report | The target name or browser type is invalid, unavailable on the plan, or not included in the active configuration. | Check the target object against the current configuration docs and verify browser availability for the account. |
| Unexpectedly many snapshots | Every variant is being captured against every configured target and run. | Calculate variants × targets × runs. Remove redundant combinations or use supported selective runs. |
| Mobile layout looks like desktop | The viewport is not set as intended, or the page uses a different responsive mode than expected. | Verify width and height order, inspect the report metadata, and choose a width on the correct side of the CSS breakpoint. |
| Images or fonts are missing | Assets have not loaded or their host is blocked by request restrictions. | Wait for assets and fonts; inspect logs for blocked requests and allow required hosts. |
| Differences appear intermittently | Dynamic content, animations, changing remote assets, or asynchronous rendering. | Use deterministic fixtures, stabilize time and animation, wait for required content, and restrict uncontrolled external requests. |
| Configuration fails after a package update | The project uses syntax from a different Happo version. | Check installed package version and migrate configuration using the current official docs. |
| Safari or iOS Safari target cannot run | Browser coverage depends on the Happo plan. | Confirm the plan’s included browsers on the current pricing page or use an included target during evaluation. |
Or skip the browser setup
If you need a screenshot of a URL rather than a visual-regression baseline across browsers, ScreenshotNeo is a website screenshot API and MCP server. It takes one GET request and returns an image or PDF; see the API documentation.
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}`);
ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, with verdict and billing headers on each response. Its MCP server gives AI agents tools to take screenshots, get page info, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000, and every feature is on every plan.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
FAQ
Can I use different viewport sizes in the same Happo run?
Yes. Define multiple targets with different viewport values and run the integration against those targets.
Does Happo run on real browsers?
Happo describes its browser captures as running in real browsers. The available browser set depends on the plan.
Should every story be captured in every browser?
Only if that coverage has value. Start with states and browser/viewport combinations tied to actual user risk, then expand based on findings.
Is this the same as taking a production website screenshot?
No. Happo is used here for repeatable visual comparisons of stories or test states. ScreenshotNeo is suited to one-off URL screenshot and PDF capture through an API or MCP client.
Primary references: Happo configuration, pricing and snapshot definition, Storybook integration, Cypress integration, Playwright integration, and hostname allowlisting and vendor-reported flake example.


