Skip to content
Docs

Capture a page

Early access. Tell us what you're building and we'll set you up. Contact us

POSTapi.lempile.com/accounts/{account_id}/capture

A JPEG of one page, opened in the X account's own browser and proxy. Read-only: a new tab, cookie banners and X's overlays hidden with CSS (never clicked), the picture, the tab closed. Not a write: no Idempotency-Key, no receipt, not paced.

It opens only:

  • A public X post, exactly https://x.com/<handle>/status/<digits> (handle 1–15 letters, digits or _, not i; 1–25 digits; no query, fragment or trailing slash; x.com only). The picture is the post's own article, read from the account's own signed-in X, taken only when X shows it under that handle, ending at its action bar. No clip.selector; with x_post: { counts: false } the time and views row and the action bar are left out too.
  • A status page: https://<host>, https://<host>/ or https://<host>/incidents/<id> (8–40 letters or digits) on www.vercel-status.com, www.githubstatus.com, status.supabase.com, www.cloudflarestatus.com, status.openai.com, status.claude.com, www.netlifystatus.com, status.render.com, status.flyio.net, status.clerk.com, resend-status.com.
  • The account's own X: https://x.com/<its handle> and https://x.com/i/account_analytics.
  • News pages: any page on blog.google, developers.google.com, blogs.bing.com, www.seroundtable.com, techcrunch.com; https://news.ycombinator.com/item?id=<digits>; and any page on a site Lempile added to your workspace's list.

Hosts match exactly. The browser checks the address again before opening it and after the page loads. When the page gave no picture the answer is still 200, with ok: false and the browser's code.

Scope: accounts.write.

Authentication

X-API-KEY header·A Lempile API key, made in the dashboard under Access tokens.

Path parameters

  • account_idstringrequired

    Lempile id, X user id or handle.

Request body

  • urlstring · urirequired

    One of the addresses the capture opens, exactly.

  • widthinteger

    CSS pixels (under 768, X and most sites draw their phone layout).

    Default520≥ 320 · ≤ 1280
  • dprinteger
    Default2≥ 1 · ≤ 3
  • clipobject
    ›Show fields
    • maxHeightinteger

      CSS pixels: the picture stops there. max_height works too.

      Default1600≥ 100 · ≤ 4000
    • selectorstring

      The picture is that element. Not on an X post.

      ≤ 200 chars
  • x_postobject

    X posts only: on another address it answers 400.

    ›Show fields
    • countsboolean

      false leaves out the post's time and views row and its action bar (no views, replies, reposts, likes or bookmarks); the picture ends 16 px under its last content.

      Defaulttrue

Responses

200

The picture (ok: true), or why there is none (ok: false with code).

›

application/json

  • objectanyrequired
    AlwaysPageCapture
  • okbooleanrequired
  • account_idstringrequired
  • urlstringrequired
  • final_urlstring

    ok: true: the address the page ended on.

  • titlestring
  • widthinteger

    Pixels of the JPEG: CSS width times dpr.

  • heightinteger
  • jpeg_base64string

    ok: true: the JPEG, base64, no data: prefix.

  • captured_atstring · date-timerequired
  • codestring

    ok: false: why there's no picture. x_post_author_mismatch: X shows the post under another handle than the address's, or no author it could read. x_post_protected: The post is from a protected account. x_post_deleted: X says the post doesn't exist: deleted, or never posted. x_post_age_restricted: X shows the post only behind an age or sensitive-content warning (never clicked through). x_post_unavailable: X shows its "This post is unavailable" notice. x_post_not_loaded: X ran but didn't show the post within 25 seconds. x_signed_out: X is signed out in the account's browser. x_app_not_loaded: X's app didn't load in the account's browser. left_allowed_hosts: The page went to another address after it loaded. url_not_allowed: The browser's own check refused the address. element_not_found: No element for clip.selector within 10 seconds. browser_busy: The account's browser was on another job: try again in a minute. capture_blank: The picture came out blank (almost all of it one colour), or X drew the post's box empty: it isn't returned. counts_not_hidden: Asked with x_post: { counts: false }, but the views row and action bar couldn't be hidden: no picture, never one with counts. no_picture: The browser gave no picture. capture_failed: The capture stopped.

    One ofx_post_author_mismatchx_post_protectedx_post_deletedx_post_age_restrictedx_post_unavailablex_post_not_loadedx_signed_outx_app_not_loadedleft_allowed_hostsurl_not_allowedelement_not_foundbrowser_busycapture_blankcounts_not_hiddenno_picturecapture_failed
  • detailstring

    ok: false: the same, in words.

400

errors/invalid_parameters: an address it doesn't open (the detail lists them), a field out of range, or clip.selector on an X post. errors/missing_parameters: no url.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

401

Missing or invalid API key ({error, message}), errors/disconnected_account, or errors/reauth_required when X is signed out in the account's browser.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

402

subscription_required: the workspace has no active trial or subscription.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

403

errors/insufficient_permissions: the key lacks accounts.write.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

404

errors/resource_not_found: no such account in this workspace, or it isn't an X account.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

422

errors/proxy_auth_failed or errors/proxy_unreachable: the account's proxy is down.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

423

errors/x_account_locked: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

503

errors/service_unavailable (the account isn't ready, or the browser runner can't be reached), errors/no_client_session, or errors/maintenance with retry_at.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

504

errors/timeout: no picture within 90 seconds. Nothing was clicked or typed.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

Was this page helpful?