ScreenshotNeo

BlogHow-to

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.

By the ScreenshotNeo team4 October 20267 min read

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.

  1. Retry without custom headers, if the page can be viewed without them.
  2. If the page requires authentication, check whether its supported authentication flow uses cookies instead of headers.
  3. For a font served externally, test whether removing or changing headers restores it; alternatively, serve the font from your own site.
  4. 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, and scroll_page=true if it is lazy-loaded.
  • Verify: request fresh=true and 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=true and wait for a selector that indicates the relevant content has appeared.
  • Verify: use an image or container that actually exists on that page; wait_for times 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 ttl according 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_until or 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.