Skip to content

Screenshot Dynamic Pages After Click and Wait

Capture SPAs, lazy sections, modals, and carousels by orchestrating click, wait, and scroll steps with deliberate delays. Learn how timing parameters interact with async rendering.

Static URLs, dynamic pixels

The address bar may not change while your UI does. Single-page applications swap views client-side; images lazy-load as you scroll; accordions hide the markup you need until clicked; carousels rotate offers on timers. A screenshot taken immediately after navigation often shows skeletons, spinners, or the wrong slide. The fix is to drive the page into the target state, then wait until rendering quiesces—exactly what click, wait, and scroll automation steps are for.

SPAs and lazy-loaded content

After navigation, wait for a root selector that indicates the framework mounted—think #app with non-empty children, or a data attribute your team already uses for tests. Then scroll through the viewport in increments so intersection observers fire and below-the-fold images request. Without scrolling, many sites never populate the DOM region you intend to capture.

If a tabbed layout hides content, add a click on the correct tab label, then wait for the panel’s active class or ARIA state before capturing.

Modals, drawers, and accordions

Overlays often live in portal nodes at the end of body. Steps should open the modal first—click the trigger button—then wait for the dialog selector (role="dialog" or a known class). Accordions may need a click per section; chain waits between clicks so CSS height transitions finish.

Carousels add timing nuance: either click the “next” control until the desired slide is active, or wait for a specific dot/indicator state. If slides autoplay, a wait with a duration can align the frame, but explicit navigation is more deterministic.

Delay and timing parameters

Two layers matter: per-step waits (until selector or timeout) and global render delay applied before the screenshot shutter. Small global delays absorb residual layout thrash from web fonts or third-party widgets. Long delays cost credits and wall time—tune them with production-like data volumes.

Detailed guidance on render delay, max wait, and related knobs appears in Screenshot timing. For how interactions compose with other features, see Page interactions.

Third-party embeds and consent banners

Analytics beacons, chat widgets, and consent management platforms shift layout height and steal focus. Where policy allows, dismiss or accept cookies via an automation step, then wait for a selector on your own main content rather than on a third-party iframe you cannot control. If an overlay obscures the region you need, prefer vendor-supported dismissal flows; avoid aggressive DOM surgery in production unless your security review explicitly covers it.

Recommended patterns

ScenarioPattern
Infinite scroll listsRepeated scroll + wait for new items until target row appears
Chart libraries (Canvas/SVG)Wait for chart container + animation frame; add short delay
Cookie bannersClick accept if required, then wait for banner node removal
Video heroesPause via JS injection or wait for poster image; avoid mid-blur frames

Example: open modal and capture

{
  "url": "https://marketing.example.com/pricing",
  "delay": 600,
  "steps": [
    { "action": "wait", "selector": "button[data-open-compare]", "timeout": 20000 },
    { "action": "click", "selector": "button[data-open-compare]" },
    { "action": "wait", "selector": "[role='dialog'] .compare-table", "timeout": 15000 },
    { "action": "wait", "duration": 400 }
  ]
}

Example: carousel to a specific slide

const steps = [
  { action: "wait", selector: ".carousel", timeout: 20000 },
  { action: "click", selector: ".carousel__dot[data-index='2']" },
  { action: "wait", selector: ".carousel__slide--active[data-index='2']", timeout: 10000 },
  { action: "wait", duration: 300 },
];
await fetch("https://api.screenshotcenter.com/api/screenshot/create", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-KEY": process.env.SCREENSHOTCENTER_API_KEY,
  },
  body: JSON.stringify({
    url: "https://www.example.com/",
    delay: 500,
    steps,
  }),
});

Anti-patterns to avoid

Oversized blanket sleeps make pipelines slow and still fail under load. Prefer selector-based waits with realistic timeouts. Avoid clicking moving targets during animations—wait for transitionend surrogates such as class changes stable for two animation frames. Do not assume desktop selectors apply when using mobile device emulation; re-test under the same profile the API request specifies.

Closing the loop

Dynamic pages are the default on the modern web; treating them like static documents is why so many screenshots look “almost right.” Compose click, wait, and scroll steps deliberately, align global delays with your heaviest third-party scripts, and consult Screenshot timing plus Page interactions whenever you adjust capture policies across environments.