How to Capture HTML Email Previews With a Screenshot API
Render email HTML into desktop and mobile previews with a screenshot API. Learn how to send raw HTML, load assets, automate captures, and understand the limits of browser rendering.
To capture an HTML email preview with a screenshot API, render your template to its final HTML, send that HTML to an endpoint that accepts HTML input, choose a viewport, wait for required assets, and save the returned image. You can preview without hosting the email at a public URL if the API accepts raw HTML. The result shows how a browser renders the markup; it does not prove how Gmail, Outlook, or another mail client will display the message.
1. Choose the preview workflow
There are three useful approaches. Choose based on whether you already have a rendered preview page and whether you need a generic browser image or email-client verification.
| Approach | Input | Use it for | Limit |
|---|---|---|---|
| HTML screenshot API | Final HTML string | Automated previews during template development, without publishing a staging page | Shows browser rendering, not actual inbox behavior |
| URL screenshot API | Reachable preview URL | Capturing an existing staging route, including its page wrapper | The URL, browser state, and timing must match what you intend to inspect |
| Email inbox or client testing tool | Test message or local inbox message | Inspecting delivered messages or verifying client-specific behavior | Capabilities and automation vary by tool |
For an API shortlist, start with ScreenshotNeo: it accepts HTML-to-image input, removes common consent banners, popups, and chat widgets before capture, and bills only clean shots. Cloudflare Browser Run documents both URL and HTML input, with configurable viewport and readiness controls. ScreenshotRun also documents raw HTML email previews using headless Chromium. Mailpit provides an HTML screenshot in its web UI, but its documentation says screenshot generation is not automated through its API. Cloudflare docs, ScreenshotRun guide, Mailpit docs.
2. Prepare the exact HTML you want to inspect
Render the template before taking the screenshot. If your email uses a template engine, supply representative data and use the generated output that you plan to send. This catches both markup issues and data-dependent layout problems.
- Run your normal template build or rendering step.
- Substitute realistic values for names, URLs, prices, and optional sections. Include long and short values if they can change layout.
- Keep the HTML output with the preview or record the template revision so a visual difference can be traced later.
- Decide whether external images and fonts should be fetched. Verify that the screenshot service can reach them, or make required resources available in a controlled way.
Do not invent a public URL just to pass the markup to an API that supports raw HTML. If the service accepts only a URL, serve the rendered preview from an access-controlled test route and submit that URL instead. Keep API credentials on the server or in CI secrets; do not put them in browser-side JavaScript.
3. Capture raw HTML with Cloudflare Browser Run
Cloudflare Browser Run’s screenshot endpoint accepts url or html. Its REST endpoint requires a Browser Rendering edit token. The following cURL pattern submits HTML and saves the image; set the account identifier and token through environment variables in your shell or CI secret store. Check the current endpoint documentation for the required account-specific path and request format before using it.
# Store CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN in the environment.
# Replace the endpoint path if Cloudflare's current API format differs.
curl -X POST \
"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/browser-rendering/screenshot" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
-H "Content-Type: application/json" \
--data-binary @request.json \
--output email-desktop.png
For this request, put the rendered HTML and viewport in request.json, following the current fields shown in the Cloudflare screenshot endpoint docs. Cloudflare also documents a Workers binding that can call Browser Rendering without a REST API token. The endpoint supports options including viewport dimensions, clipping or full-page capture, and navigation/load behavior. Its documented default viewport is 1920 by 1080; set dimensions explicitly for repeatable email previews. JavaScript-heavy pages may be incomplete if captured before rendering finishes, so use the documented wait controls or wait for a selector.
The exact JSON field names and response encoding are provider-specific and may change. Follow the current provider documentation rather than assuming that every HTML screenshot endpoint uses the same schema. If the endpoint returns JSON metadata with an image payload rather than image bytes, decode that payload before writing the file.
4. Capture desktop and mobile widths
Responsive email layouts need separate captures at the widths you care about. A desktop image cannot show whether a mobile breakpoint behaves correctly. ScreenshotRun’s guide uses 600-pixel and 375-pixel examples; those are example capture widths, not universal email standards. Select widths that match your design and QA needs, then use the same values on every run.
# Conceptual request shape only: use the exact schema of your chosen API.
{
"html": "<!doctype html>...rendered email HTML...",
"viewport": { "width": 600, "height": 1200 },
"fullPage": true
}
Repeat with a 375-pixel viewport for a narrow mobile preview, and consider an intermediate width if the layout changes near a breakpoint. Full-page capture is useful for long messages; a fixed-height viewport is useful when you need to inspect only the opening portion. Ensure the output image includes the whole email when comparing revisions.
5. Wait for images, fonts, and other assets
The pixels depend on when the capture occurs and whether referenced resources load. For URL captures or content that runs JavaScript, use the provider’s readiness controls, such as waiting for navigation, a selector, or a deliberate delay where available. For direct HTML input, confirm what the API does with remote assets and how it handles relative URLs.
- Use absolute, reachable URLs for remote images and fonts unless the service documents another asset mechanism.
- Do not assume that a browser’s local filesystem or your development server is visible to a remote capture service.
- If a font is not ready, the browser may use a fallback and change line wrapping. For a stable preview, wait for the font load when supported or use a reliable fallback stack.
- Some services proxy remote assets. Mailpit documents that its screenshot feature proxies external resources, requires host resolution, and by default requires valid HTTPS certificates for assets. It also restricts proxied requests to internal networks by default.
- Keep image hosting stable during visual comparisons. A missing image may change both appearance and the rendered page height.
Cloudflare’s documentation describes rendering HTML and JavaScript before capture and provides wait controls. Mailpit’s asset behavior applies to Mailpit; do not assume another provider has identical proxying or network rules. Cloudflare screenshot docs, Mailpit screenshot docs.
6. Save previews and make them repeatable
Save the response as a PNG or another supported image format, and associate it with the source HTML or template revision. In a build or QA workflow, capture the same desktop and mobile sizes after each meaningful change. Compare output files or use a visual-diff step in your own pipeline; screenshot services document capture, but version tracking and comparison are workflow choices.
For a URL-based preview, make the route deterministic: use stable test data, avoid personalized content, and control authentication and browser state according to the provider’s options. For raw HTML, ensure the exact HTML string and asset URLs are recorded. Treat screenshots containing personal or confidential content as sensitive artifacts.
7. Know what a browser screenshot can and cannot prove
A screenshot API is a fast way to inspect browser-rendered markup. It is useful for checking spacing, colors, image loading, content, and responsive behavior in a controlled viewport. It does not reproduce every email client. ScreenshotRun explicitly notes that Chromium does not simulate Outlook’s Word rendering engine or Gmail’s CSS stripping. If client fidelity is an acceptance requirement, use a real-client email testing workflow after the browser preview. Mailpit also documents that Outlook-specific markup such as <o:p> can be rewritten or removed in its screenshot path, affecting line spacing.
For local message inspection, Mailpit’s UI screenshot can help, but its documented screenshot feature is not an automated API. For client coverage, verify the current capabilities of the email-testing service you choose rather than treating a generic browser capture as proof. ScreenshotRun email preview guide, Mailpit HTML screenshot docs.
8. Or skip the browser setup
ScreenshotNeo’s API docs describe a one-call screenshot API. Send rendered email HTML to its HTML-to-image option, set the dimensions you need, and save the image response. The base API is https://api.screenshotneo.com/v1/shot; use the current docs for the exact HTML parameter and output 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}`);
await Bun.write('shot.webp', res);
These ready-to-run examples capture a URL; adapt the target and use the documented HTML input for a rendered email string. ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot, and each step can be turned off. Bot checks, blank pages, and failed loads are never billed; response headers report the page verdict and whether the shot was billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
9. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The result is blank or only partly rendered | Capture happened before JavaScript or page content finished | Use a documented wait condition, selector, or delay. For direct HTML, verify how the endpoint waits before capture. |
| Remote images are missing | Asset URL is relative, unreachable from the capture service, blocked, or not yet loaded | Use reachable absolute URLs, check host resolution and HTTPS certificates, and confirm the provider’s remote asset rules. |
| Text wraps differently between runs | Web font did not load consistently, viewport changed, or input content differs | Pin the viewport, wait for fonts where possible, and use identical rendered HTML and assets. |
| Request is unauthorized | Missing, expired, or insufficient API token | Check the provider’s current authentication requirements; for Cloudflare REST, use a Browser Rendering edit token and keep it in a server-side secret. |
| HTML is rejected or treated as a URL | Wrong input field or endpoint mode | Confirm the endpoint accepts raw HTML and use its documented field names. Do not send HTML to a URL-only endpoint. |
| Outlook spacing differs from the screenshot | Generic browser rendering does not match Outlook’s Word engine; Outlook-specific markup may be transformed in some tools | Use the screenshot for iteration, then verify in an email-client testing workflow. |
| Mobile layout looks like desktop | Capture viewport is too wide or responsive rules depend on a different width | Set an explicit narrow viewport and capture a separate image for each relevant width. |
10. Performance, reliability, and cost
- Performance: Each viewport and template revision requires a capture. Batch requests where a provider supports them, but balance concurrency against rate limits and asset-host capacity. Waiting for all network activity can be slow when third-party resources never become idle; prefer a meaningful selector or readiness condition when available.
- Reliability: Keep the HTML, viewport, asset versions, and capture options consistent. Retry transient network failures with bounded backoff, and distinguish a failed capture from a valid image in your pipeline. Do not treat a successful HTTP response alone as proof that the page rendered correctly.
- Cost: Check the provider’s current pricing and how it counts requests, failed renders, retries, and output formats. No neutral price comparison is established by the cited research. ScreenshotNeo states that only clean shots are billed and offers 1,000 free shots monthly; see its current product and docs pages for options and plan details.
- Data handling: Email HTML can contain campaign content, tracking URLs, or personal data. Send only appropriate test data, protect credentials, and review the provider’s current data-handling terms before submitting sensitive content.
Frequently asked questions
Can I preview an email without hosting it?
Yes, if the screenshot API accepts raw HTML. Provide the rendered template string and ensure any linked assets are reachable. Otherwise, use a private preview URL if the provider requires URL input.
Does a screenshot API tell me what Gmail or Outlook will show?
No. A generic browser screenshot is a browser-rendered preview. Use email-client testing when the target client’s rendering is what you need to validate.
Should I capture one long image or multiple screen-sized images?
Use full-page output to inspect the entire message and fixed-height captures to review the visible opening region or match a specific viewport. For responsive QA, make separate captures at the widths you need.
Can Mailpit automate screenshot capture through its API?
Its documentation describes screenshot generation through the web UI and says it cannot be automated via its API. Check current Mailpit docs if that capability is important to your workflow.


