ScreenshotNeo

BlogHow-to

How to Fix ApiFlash Screenshots That Fail on Indian Websites in Regional Languages

Diagnose ApiFlash errors, wrong locales, missing glyphs, late content, stale captures, and access problems with targeted checks and settings.

By the ScreenshotNeo team4 October 20268 min read

ApiFlash screenshots that fail on Indian websites can have several different causes: an API error, the wrong locale, capture before content or fonts load, missing glyphs, a stale cached image, or a bot check or login wall. There is no single India-specific fix. Start by checking the HTTP status and response body, then follow the branch that matches what the screenshot actually shows.

This guide uses ApiFlash’s documented parameters and behavior. No particular Indian-language site or failing response was supplied, so the checks below are diagnostic steps rather than claims that a specific site was tested.

1. Check whether the API returned an image

Do not save every response as a PNG and assume the capture succeeded. Check the HTTP status and content type first. ApiFlash documents these common response statuses:

Status Likely issue Next check
400 Invalid parameter or target cannot be captured Read the error message; JSON response mode may include additional details.
401 Invalid or revoked access key Check the key and how it is passed.
402 Monthly quota exhausted Check account usage and quota.
403 Requested feature is not supported by the plan Check whether that parameter requires a different plan.
429 Too many requests Reduce request rate and retry with backoff.
500 Capture failure Inspect the response body and retry after checking the target and capture settings.

A useful first pass is to make one request with the smallest set of parameters that reproduces the issue. Add language, wait, cache, and access options one at a time so you can tell which change affects the result.

2. Request the language the site understands

ApiFlash’s accept_language parameter sets the Accept-Language request header. Set it to the locale the site uses, such as hi-IN for Hindi or the appropriate locale for the target language:

curl -G 'https://api.apiflash.com/v1/urltoimage' \
  --data-urlencode 'access_key=YOUR_APIFLASH_KEY' \
  --data-urlencode 'url=https://example.com' \
  --data-urlencode 'accept_language=hi-IN' \
  -o capture.png

Replace the example domain and locale with the actual target and its supported language. The header is a hint to the site; it does not force every site to change language. Check whether the target chooses language through a locale-specific URL path, a cookie, or application state. If it does, use the matching URL or session settings as well.

Compare the result with the same URL without accept_language. If both images show the same language, the site may ignore the header or use another language-selection mechanism.

3. Wait for the content or font that is missing

A screenshot can be captured before client-rendered text, a translation bundle, or a web font is ready. ApiFlash documents wait_until values network_idle (the default), dom_loaded, and page_loaded. It also supports wait_until_timeout up to 30 seconds, wait_for for a CSS selector, and delay up to 10 seconds.

When a specific region is missing, a selector wait is usually more diagnostic than adding an arbitrary delay:

curl -G 'https://api.apiflash.com/v1/urltoimage' \
  --data-urlencode 'access_key=YOUR_APIFLASH_KEY' \
  --data-urlencode 'url=https://example.com' \
  --data-urlencode 'accept_language=hi-IN' \
  --data-urlencode 'wait_for=main article' \
  --data-urlencode 'wait_until_timeout=30000' \
  -o capture.png

Use a selector that appears only when the relevant content has rendered. ApiFlash aborts if the wait_for selector is not found after 15 seconds. If the page has no reliable selector, compare page_loaded and network_idle, then use a short delay only when the page needs time after its load event. A delay is capped at 10 seconds and may still miss unpredictable content.

4. Diagnose missing or incorrect glyphs

If the page structure and language are correct but characters appear as boxes, substitutions, or malformed clusters, inspect font delivery and rendering. ApiFlash says its screenshots use Chrome on Linux, where installed system fonts differ from Windows and macOS. It recommends that websites serve their own fonts instead of relying on fonts installed on a particular machine.

  1. Open the target page in a browser and identify which font is used for the affected text.
  2. Check whether the page serves that font itself or relies on a system font.
  3. Check whether the font request succeeds. A custom header configured for the capture applies to all requests, including font requests, and can interfere with external font loading.
  4. Compare the screenshot with the page’s actual text and font resources; do not treat every shaping or glyph problem as a generic character-encoding error.

Indian languages use multiple scripts and have script-specific text-processing behavior. A language header can select translated content, but it cannot supply a missing font or correct a page’s text-rendering implementation. For script background, see the Unicode Consortium’s Indian-language feedback material and the Unicode Standard.

5. Rule out a cached screenshot

ApiFlash may return cached output for identical parameters. To see whether the target has changed, request a fresh capture:

curl -G 'https://api.apiflash.com/v1/urltoimage' \
  --data-urlencode 'access_key=YOUR_APIFLASH_KEY' \
  --data-urlencode 'url=https://example.com' \
  --data-urlencode 'accept_language=hi-IN' \
  --data-urlencode 'fresh=true' \
  -o fresh-capture.png

fresh=true requests a new capture; it does not invalidate the previously cached screenshot. If the fresh image changes, compare capture time and page state before changing language or font settings.

6. Check bot protection and authenticated pages

A challenge page, access denial, or login screen points to access conditions rather than regional-language support. ApiFlash documents proxy, cookie, and header options that may be relevant for these cases. Use the cookies or headers required by the target session, and consider a suitable proxy when the target’s bot protection blocks the capture. These options do not guarantee access.

Keep custom headers as narrow and correct as possible: ApiFlash applies them to all requests, so a header intended for the document can also affect images, scripts, and fonts. Avoid sharing access keys or session cookies in logs or public code.

Complete diagnostic request examples

These examples request Hindi content, wait for the main content, and bypass a cached result. Replace the key, target URL, locale, and selector with values appropriate to the page. Check the response status and content type before treating the response as an image. ApiFlash’s documentation lists the capture options and error behavior: ApiFlash Screenshot API documentation; its FAQ discusses language selection, fonts, bot protection, and authentication: ApiFlash FAQ.

cURL

curl -G 'https://api.apiflash.com/v1/urltoimage' \
  --data-urlencode 'access_key=YOUR_APIFLASH_KEY' \
  --data-urlencode 'url=https://example.com' \
  --data-urlencode 'accept_language=hi-IN' \
  --data-urlencode 'wait_for=main article' \
  --data-urlencode 'wait_until_timeout=30000' \
  --data-urlencode 'fresh=true' \
  -o capture.png

Python

import requests

params = {
    "access_key": "YOUR_APIFLASH_KEY",
    "url": "https://example.com",
    "accept_language": "hi-IN",
    "wait_for": "main article",
    "wait_until_timeout": 30000,
    "fresh": "true",
}
response = requests.get(
    "https://api.apiflash.com/v1/urltoimage",
    params=params,
    timeout=60,
)
content_type = response.headers.get("Content-Type", "")
if not response.ok or not content_type.startswith("image/"):
    raise RuntimeError(
        f"ApiFlash returned HTTP {response.status_code} "
        f"({content_type}): {response.text[:1000]}"
    )
with open("capture.png", "wb") as image_file:
    image_file.write(response.content)

Node.js

const params = new URLSearchParams({
  access_key: 'YOUR_APIFLASH_KEY',
  url: 'https://example.com',
  accept_language: 'hi-IN',
  wait_for: 'main article',
  wait_until_timeout: '30000',
  fresh: 'true',
});
const response = await fetch(
  `https://api.apiflash.com/v1/urltoimage?${params}`
);
const contentType = response.headers.get('content-type') || '';
if (!response.ok || !contentType.startsWith('image/')) {
  const body = await response.text();
  throw new Error(
    `ApiFlash returned HTTP ${response.status} (${contentType}): ${body.slice(0, 1000)}`
  );
}
const fs = await import('node:fs/promises');
await fs.writeFile('capture.png', Buffer.from(await response.arrayBuffer()));

7. Troubleshoot by symptom

Symptom Likely cause Try this
The response is JSON or text, not an image Invalid request, key, quota, plan, rate limit, or capture error Read status and body; check parameters, credentials, quota, feature access, and request rate.
Page is readable but in the wrong language The site chose another locale or ignored the request header Set accept_language; inspect locale paths, cookies, and app settings.
Text or a content section is absent Capture happened before client content rendered Wait for the content selector or choose an appropriate wait_until condition.
Characters are boxes or look different locally Missing font, failed font request, or Linux system-font difference Verify font requests and serve required fonts from the site; review custom headers.
Repeated request gives an old image Cached output Set fresh=true and compare the newly captured result.
Screenshot shows a challenge or login page Bot protection or missing session credentials Check target access; use documented cookies, headers, or an appropriate proxy where authorized.
Selector wait fails The selector is wrong or never appears within the wait window Confirm the selector in the page and account for the documented 15-second selector limit.
Font disappears only after adding a header The header affects font requests too Remove or correct the header and retry; headers apply to all requests.

Performance, reliability, and cost considerations

  • Wait only for what matters. A relevant selector or page-state condition can avoid both premature captures and unnecessary delay. The documented delay ceiling is 10 seconds and wait_until_timeout ceiling is 30 seconds.
  • Separate diagnosis from production retries. First identify whether the failure is an API error, language selection, rendering, cache, or access issue. For throttling, reduce concurrency and retry gradually rather than repeating requests immediately.
  • Do not infer reliability from one capture. Dynamic content, session state, fonts, and bot protection can differ between requests. Record the status and relevant response headers/body alongside the image when diagnosing failures.
  • Use freshness deliberately. Fresh captures are useful for debugging changing pages, while identical requests may otherwise use cached output. A cache hit can be appropriate when the page is stable.
  • Track account constraints. ApiFlash documents quota, plan, and rate-limit errors separately; check usage and plan support before treating them as target-site failures.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its single GET endpoint can return PNG, JPEG, WebP, or PDF. For a basic capture, use the documented API parameters; the ScreenshotNeo API docs cover configuration.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

Or use Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Or use Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners are accepted and removed before capture; more than 60 known consent platforms, newsletter popups, and chat widgets can be removed, and each step can be turned off.
  • Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Response headers say the page verdict and whether the capture was billed.
  • An MCP server exposes screenshot, page-info, and PDF tools for Claude, Cursor, and other MCP clients.
  • The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000. Every feature is available on every plan.

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.

FAQ

Will accept_language=hi-IN translate a page?

No. It sets the request language header. The website still decides whether and how to use that signal.

Does an encoding parameter fix missing Indian-script glyphs?

Not necessarily. Check the actual font requests, rendered text, and site language behavior before changing character encoding.

Does fresh=true clear ApiFlash’s cache?

No. It requests a fresh capture but does not invalidate an older cached screenshot.

Can a proxy guarantee a capture through bot protection?

No. A proxy may help depending on the protection, but access is not guaranteed.