How to Take Microlink Screenshots of JavaScript-Rendered Pages
Capture the rendered app state with Microlink by waiting for the content you need, then choosing the right interaction and screenshot options.
A Microlink screenshot can show a spinner or empty shell when the browser captures a JavaScript app before it has hydrated or loaded its data. Make the capture wait for a page-specific element that proves the content you need is present. Use a navigation lifecycle event such as domcontentloaded to begin the page work sooner when appropriate, then use waitForSelector to wait for the rendered content.
This guide covers Microlink’s JavaScript SDK and REST request patterns, interactions for tabs and lazy-loaded sections, capture geometry, failure cases, and a ready-to-use alternative.
1. Identify a reliable readiness signal
Choose a DOM element that appears only when the specific content you want has rendered. For a chart, that might be its SVG or canvas; for a data table, a row or heading populated by the app. A generic lifecycle event only says something about navigation. It does not prove that client-side rendering, hydration, or an API response has completed.
- Open the target page and identify a stable CSS selector for the finished content.
- Decide whether the content is present on initial load or requires a click or scroll.
- Wait for the content-specific selector before taking a viewport or full-page screenshot.
- Set a viewport or capture mode that includes the content you need.
Prefer this selector-based approach over a fixed delay when a stable element exists. The selector wait can finish as soon as the element appears. A fixed timer always waits its full duration and may still be too short under slower conditions.
2. Capture rendered content with the Microlink JavaScript SDK
Install the SDK in a Node.js project and set the API key in the environment. The following example follows Microlink’s documented SDK pattern; it uses an illustrative URL and selector that you must adapt to your application.
npm install microlink.io
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { url } = await microlink.screenshot('https://app.example.com/report', {
waitUntil: 'domcontentloaded',
waitForSelector: '.chart svg'
})
console.log(url)
Use a selector tied to the finished content, not a generic app root that exists while the app is still loading. The returned url is the SDK’s screenshot result. Consult Microlink’s current SDK and API documentation for current authentication and response handling before integrating it.
3. Request a screenshot through the REST API
Microlink’s documented URL request pattern sets screenshot=true, disables metadata when it is not needed, chooses a navigation wait, and supplies the selector. Adapt the selector and target URL to the page you own or are authorized to capture.
curl -G 'https://api.microlink.io' \
--data-urlencode 'url=https://app.example.com/report' \
--data-urlencode 'screenshot=true' \
--data-urlencode 'meta=false' \
--data-urlencode 'waitUntil=domcontentloaded' \
--data-urlencode 'waitForSelector=.chart svg'
The response format and screenshot URL handling depend on Microlink’s API response. Check its current REST documentation for authentication requirements, output options, and response schema. The dossier does not establish a current endpoint contract or authentication requirement for every account, so do not assume these details without checking.
4. Prepare tabs, expandable panels, and lazy-loaded sections
Content revealed by a tab or control
If a chart or panel is hidden until a user action, perform that action before waiting for the resulting content. Microlink’s browser automation materials document page actions such as clicking. For example, click the revenue tab and then wait for the chart in its panel. Confirm the current request shape for combining actions and screenshot parameters in Microlink’s documentation.
// Illustrative interaction sequence; confirm current API syntax in Microlink docs.
click: '#tab-revenue'
waitForSelector: '#panel-revenue canvas'
The important sequence is action, readiness condition, capture. Waiting for a selector that is already present in a hidden panel may not prove that the panel has become visible or that its data has loaded; use a selector specific to the rendered result when possible.
Content loaded on scroll
Some pages load images or sections only after they enter the viewport. Scroll the target section into view, wait for an element inside it, and request a full-page screenshot if the output should include the whole document. If only the target region matters, consider capturing that element instead of the full page.
// Illustrative sequence; check the current browser automation parameter syntax.
scroll: '#annual-report'
waitForSelector: '#annual-report .chart svg'
fullPage: true
Microlink documents screenshot.element capture and says that it waits for the target element to become visible. When capturing that element, a separate selector wait is needed only if you must wait for another condition, such as data rendering inside it. For viewport or full-page capture, add a content-specific wait when initial navigation completion is not enough.
5. Choose wait and capture options
| Option or strategy | Use it when | Trade-off |
|---|---|---|
waitUntil |
You need to choose a navigation lifecycle point, such as domcontentloaded. |
Navigation readiness does not establish that the app’s data or UI is ready. |
waitForSelector |
A stable, page-specific element indicates the desired content has rendered. | If the selector never appears, the request can run out of time. |
waitForTimeout |
No reliable DOM condition exists. | A fixed delay can be wasteful on fast loads and insufficient on slow ones. |
| Network-idle wait | The page settles its requests and does not keep long-lived connections open. | Persistent requests can prevent the condition from completing. |
javascript: false |
The page is complete in its initial HTML and does not need scripts. | Do not disable JavaScript for a client-rendered application that needs it. |
| Viewport screenshot | You need the visible browser area at a chosen viewport size. | Content outside the viewport will not be included. |
| Full-page screenshot | You need the whole document, including below-the-fold content. | Lazy content may need scrolling and a readiness wait first. |
| Element screenshot | You need a particular visible component, such as a chart. | The element must be identifiable and visible; consult the parameter reference for the current syntax. |
| Device or viewport settings | The screenshot must match a target screen or layout. | Choose dimensions that actually expose the relevant responsive state. |
The official dynamic-content guide states a 30-second request timeout for the free endpoint and 60 seconds for Pro. These are vendor-published limits from the research date, not a performance guarantee; recheck Microlink’s current documentation and plan details before relying on them. Keep navigation and content waits within the applicable request timeout.
6. Troubleshoot empty, stale, or incomplete screenshots
| Symptom | Likely cause | What to change |
|---|---|---|
| Spinner or empty app shell | The capture started after navigation but before the app rendered its data. | Wait for a selector that appears with the finished content, such as a chart SVG or populated result. |
| Selector wait times out | The selector is wrong, conditional, hidden behind an interaction, or absent because the page failed. | Inspect the live DOM, correct the selector, trigger the necessary action, and make sure the target URL is reachable. |
| Screenshot shows the wrong tab | The capture did not activate the desired tab, or it waited for a selector unrelated to that tab’s content. | Click the intended tab and wait for an element specific to its panel. |
| Below-the-fold section is missing | The section is lazy-loaded and was never brought into view, or the screenshot is viewport-only. | Scroll the section into view, wait for its content, and use full-page capture when required. |
| Request exceeds its timeout | The page is slow, a fixed wait is too long, a selector never appears, or network-idle never occurs. | Prefer a specific selector, remove unnecessary waits, avoid network-idle on pages with persistent requests, and check the current plan timeout. |
| Screenshot is delayed despite a fast page | A fixed timeout waits for its full duration. | Replace it with a selector wait that completes when the content appears. |
| Static page is unnecessarily slow | The capture waits for JavaScript or extra conditions that the page does not need. | Remove unnecessary waits; if the initial HTML is complete and scripts are not required, use the documented JavaScript-disabled option. |
7. Reliability, latency, and cost considerations
- Reliability: Tie the wait to the content being documented. A page-wide lifecycle event is weaker evidence than the chart, table, or panel you need.
- Latency: A selector wait can finish as soon as its condition appears. A fixed delay adds its full duration on every request. Long-lived network activity can make network-idle waits unsuitable.
- Timeout risk: Missing selectors and persistent requests can consume the request budget. Use bounded waits and verify the applicable plan timeout in current documentation.
- Capture geometry: Match viewport dimensions, device preset, element versus viewport capture, and full-page behavior to the output’s purpose.
- Cost: The research dossier does not establish Microlink’s current pricing. Check the vendor’s current pricing page and plan terms before estimating production volume.
8. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. A single GET request returns a PNG, JPEG, WebP, or PDF. The request below captures a URL; ScreenshotNeo’s full options include custom waits and selectors, interactions, full-page and element capture, viewport and device settings, and more. See the ScreenshotNeo API documentation for parameter details.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie banners, popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. Response headers report the page verdict and billing status.
- An MCP server lets AI agents use
take_screenshot,get_page_info, andcapture_pdf. - 1,000 screenshots a month are free with no card. Paid plans start at $5 for 3,000 screenshots.
Sign up free for 1,000 screenshots a month with no card.
9. Frequently asked questions
Does domcontentloaded mean my JavaScript app is ready?
No. It is a navigation lifecycle event. Wait for an element that demonstrates the particular app content you want has appeared.
Should I use a delay or wait for a selector?
Use a selector when a stable one exists. Use a fixed delay only when there is no reliable page condition to observe, and keep it within the request timeout.
Do I need a separate wait for an element screenshot?
Microlink’s guide says element capture waits for its target to be visible. Add another wait when you need to ensure some other content condition, such as data inside the element, has completed.
Can I turn JavaScript off?
Only when the page’s initial HTML already contains everything needed for the screenshot. Keep it enabled for client-rendered applications.


