Why Is My ApiFlash Screenshot Missing Images or Fonts?
Missing images or fonts in an ApiFlash screenshot? Check capture timing, lazy loading, font delivery, custom headers, and cached results.
If an ApiFlash screenshot is missing images or fonts, first check when the capture happens, how the page loads those assets, whether custom headers affect external requests, and whether ApiFlash returned a cached screenshot. The right fix depends on the page: try an appropriate wait_until condition, wait for a page-specific selector, trigger lazy loading with scrolling, inspect font delivery and headers, then repeat with fresh=true. These steps help isolate the cause; without the target URL and request configuration, no single cause can be confirmed.
1. Check when ApiFlash captures the page
ApiFlash documents three wait_until values. Its default is network_idle. Choose based on when the page’s relevant content and assets become ready:
| Value | What it waits for | When to try it |
|---|---|---|
dom_loaded |
The initial HTML document. It does not wait for stylesheets and images. | Only when the initial DOM is the intended capture state or you add another readiness check. |
page_loaded |
The page and dependent resources. | When images, stylesheets, or other dependencies need time to load. |
network_idle |
The page loading followed by a quiet network. | The documented default; useful for pages whose requests eventually settle. |
A page with polling, analytics, or other continuous network traffic may not become idle promptly. In that case, wait for the particular content needed in the screenshot rather than assuming that one global load condition fits every page. ApiFlash’s current API documentation describes these conditions and parameters in its API documentation.
2. Wait for the content that matters
Use wait_for with a CSS selector that appears when the image or relevant content is ready. ApiFlash documents a maximum 15-second wait; the request aborts if the selector does not appear within that limit. Choose a stable selector that represents the content, such as a product gallery container, rather than a transient animation element.
For lazy-loaded content, set scroll_page=true to trigger page scrolling. Some pages only request images when their elements approach the viewport. Scrolling can also trigger animations, so the resulting capture state may differ from a page that has not been scrolled.
A fixed delay can wait up to 10 seconds after page load. ApiFlash recommends wait_for or wait_until where possible because they express a readiness condition instead of always pausing for a guessed duration.
3. Check how the fonts are served
ApiFlash captures pages with Chrome on Linux. A page that relies on fonts installed only on a user’s Windows or macOS system can render differently in that environment. Serve the intended font as a web font, either from your site or a web-font service. For a self-hosted font, declare it with CSS:
@font-face {
font-family: "Brand Sans";
src: url("/fonts/brand-sans.woff2") format("woff2");
font-style: normal;
font-weight: 400;
font-display: swap;
}
body {
font-family: "Brand Sans", sans-serif;
}
Confirm that the font URL is reachable by the capture and that its response is a font file rather than an authentication page or error document. ApiFlash’s FAQ advises serving the site’s own fonts as the reliable solution when external font loading is affected, and explains the Linux system-font difference. The advice is specific to the observed setup; it does not establish the cause for every missing font.
4. Review custom headers and authentication
ApiFlash says the headers parameter applies to all requests, including requests for external fonts. Headers added for the page’s main document can therefore affect third-party font requests and trigger browser security restrictions.
- Retry without custom headers, if the page can be viewed without them.
- If the page requires authentication, check whether its supported authentication flow uses cookies instead of headers.
- For a font served externally, test whether removing or changing headers restores it; alternatively, serve the font from your own site.
- Keep only the headers needed for the capture and verify the font separately from the page’s HTML response.
Do not assume an API-level successful capture means every third-party asset loaded. An API error can describe a failed capture or invalid request, while a successful screenshot may still reflect an individual resource failure.
5. Rule out a cached screenshot
ApiFlash can return a cached screenshot for identical parameters. Add fresh=true to request a new capture and determine whether the missing asset is only present in an older result. The ttl parameter controls cache duration; the documented range is 0 to 2,592,000 seconds (30 days). A fresh capture is a useful diagnostic, while a suitable TTL can reduce repeated capture work when the page is stable.
6. A practical diagnostic request
Start with this cURL request and adapt the URL, selector, and wait condition to the page. It requests a fresh capture, waits for a relevant selector, and scrolls to trigger lazy loading:
curl -G "https://api.apiflash.com/v1/urltoimage" \
--data-urlencode "access_key=YOUR_API_KEY" \
--data-urlencode "url=https://example.com/products" \
--data-urlencode "wait_until=page_loaded" \
--data-urlencode "wait_for=.product-gallery" \
--data-urlencode "scroll_page=true" \
--data-urlencode "fresh=true" \
-o screenshot.png
For a page that has continuous network activity, compare page_loaded with network_idle and use a selector for the content that matters. If the gallery selector does not exist on your target page, replace it with a real selector from that page. The request options and endpoint above are ApiFlash-specific; consult its documentation for the current request format and valid options.
7. Interpret errors without overdiagnosing
| HTTP status | Documented meaning | What to check |
|---|---|---|
| 400 | Invalid parameters or an uncapturable target URL | Parameter names and values, URL encoding, and target URL accessibility. |
| 401 | Invalid or revoked key | API key and account configuration. |
| 402 | Monthly quota exceeded | Usage and quota. |
| 403 | Requested feature unsupported by the plan | Plan eligibility for the selected option. |
| 429 | Excessive requests | Request rate; reduce or space out requests. |
| 500 | Capture failure | Retry appropriately and inspect the target page and request options. |
These statuses describe API request or capture outcomes. They do not identify which individual image or font request failed inside an otherwise successful capture.
8. Troubleshooting by symptom
All images are missing
- Likely checks: the capture may happen too early, the page may require a particular ready condition, or the target may defer image loading.
- Try:
page_loaded, then a selector for the image area, andscroll_page=trueif it is lazy-loaded. - Verify: request
fresh=trueand compare against the live page’s asset behavior.
Only below-the-fold images are missing
- Likely cause: lazy loading that starts when the image approaches the viewport.
- Try:
scroll_page=trueand wait for a selector that indicates the relevant content has appeared. - Verify: use an image or container that actually exists on that page;
wait_fortimes out if the selector never appears.
The page looks right but the typeface is wrong
- Likely checks: a system font is unavailable in Linux Chrome, a web-font request is blocked, or the requested font is not served successfully.
- Try: serve the intended font as a web font and inspect custom headers that apply to external requests.
- Verify: compare with headers removed where possible and confirm the font URL responds correctly.
A change to headers made fonts disappear
- Likely cause: ApiFlash applies custom headers to external requests too, and browser security restrictions may block the font.
- Try: remove or adjust headers, use cookies if appropriate for the target site’s authentication, or self-host the font.
- Verify: make a new capture and check the font delivery path.
The screenshot does not reflect a recent page change
- Likely cause: a cached result for the same parameters.
- Try:
fresh=true. - For normal operation: set
ttlaccording to how often the target changes.
The selector wait fails
- Likely cause: selector typo, selector absent on that route, or content did not appear within the documented 15-second limit.
- Try: validate the selector against the actual page and choose an element that signals readiness.
- Alternative: use an appropriate
wait_untilor a delay of up to 10 seconds when a condition cannot be expressed with a selector.
9. Performance, reliability, and cost considerations
Waiting for the right condition improves the chance of capturing complete content, but waiting longer does not guarantee that a blocked or unavailable asset will load. Page-specific selectors can avoid unnecessary waiting on pages with continuous network activity. Scrolling can trigger lazy requests and animations, so use it only when needed for the content in the screenshot.
Cache behavior is a tradeoff: use fresh=true while diagnosing changes, then choose a ttl that matches how often the page changes. This can avoid repeated captures of identical content, though cached output may lag behind a recently updated page. ApiFlash’s cited documentation gives parameter limits, but the available research does not establish a general capture cost, uptime figure, or asset-loading guarantee.
10. Or skip the browser setup
If you want a screenshot API that handles common page cleanup and reports billing outcomes, try ScreenshotNeo. Its one-call API accepts a URL and can return PNG, JPEG, WebP, or PDF. The ScreenshotNeo API docs cover the request options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com/products \
-o shot.webp
ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and whether the capture was billed. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Does an ApiFlash error code tell me which image failed?
No. The documented status codes describe the API request or capture result, not each individual resource request within a successful screenshot.
Will network_idle always fix missing assets?
No. It is the documented default, but the cause can be lazy loading, font delivery, custom headers, or a cached result. Match the wait condition to the page and verify the asset path.
How long can ApiFlash wait for a selector?
The documented wait_for limit is 15 seconds. The request aborts if the selector does not appear by then.
Can a cached screenshot hide a successful fix?
Yes. Try fresh=true to check a new capture before concluding that a change had no effect.
Sources
- ApiFlash API documentation — wait conditions, scrolling, selector waits, delay, cache TTL, and response errors.
- ApiFlash FAQ — system fonts, external font requests, headers, and cache guidance.


