Use browser automation to open a page, wait for a target section, scroll it into view, and capture the viewport or section; then use a scheduler to run that script at the times you choose. A stable locator is generally more reliable than a hard-coded scroll distance because page layouts can change.
Choose what the screenshot should show
First decide whether you need the view around a section, a crop of the section, or the entire page. These outputs are different:
- Viewport screenshot: captures what is visible in the browser after scrolling to the target. Use this when surrounding content matters.
- Element screenshot: captures only the matched section or element. Use this for a focused record of one component.
- Full-page screenshot: captures the entire scrollable document in one image. Use it when the target is not the only content you need. It is not the same as a viewport capture positioned at a section.
Playwright documents viewport, full-page, and locator screenshots in its screenshot guide; Puppeteer also documents page and element screenshots in its screenshot guide.
Schedule a section capture with Playwright
This Node.js example navigates to a page, waits for a heading, scrolls it into view, and saves a viewport screenshot with a timestamp. Replace the URL and heading text with the page and target you need. It uses an accessible heading locator; if the site has no useful heading, use a stable test attribute or CSS selector instead.
Recommended Free Tools
#1 Best Overall
- Install Node.js, then create a project and install Playwright:
npm init -yfollowed bynpm install playwright. - Save the following as
capture-section.mjs. - Run it with
node capture-section.mjsto verify the target and output before scheduling it.
import { chromium } from 'playwright';
const url = 'https://example.com/report';
const headingText = 'Monthly results';
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto(url, { waitUntil: 'domcontentloaded' });
const section = page.getByRole('heading', { name: headingText, exact: true });
await section.waitFor({ state: 'visible', timeout: 30000 });
await section.scrollIntoViewIfNeeded();
const timestamp = new Date().toISOString().replaceAll(':', '-');
await page.screenshot({ path: `monthly-results-${timestamp}.png` });
} finally {
await browser.close();
}
The code waits for a meaningful target instead of assuming that a fixed delay means the page is ready. The Playwright locator API documents scrollIntoViewIfNeeded(); its scrolling guide notes that automatic scrolling is usually sufficient, while manual scrolling can be useful in less common cases, including screenshot positioning.
Capture only the target element
To save the matched heading rather than the visible browser view, replace the screenshot call with:
await section.screenshot({ path: `monthly-results-${timestamp}.png` });
For a larger section, locate a containing element rather than the heading itself, for example with a deliberate CSS selector: const section = page.locator('[data-testid="monthly-results"]');. Ensure that selector matches the content you actually want to capture.
Capture the entire page
To capture the full scrollable page instead of the view around the heading, use:
Rank #2
- Intuitive interface of a conventional FTP client
- Easy and Reliable FTP Site Maintenance.
- FTP Automation and Synchronization
await page.screenshot({ path: `full-page-${timestamp}.png`, fullPage: true });
Full-page capture does not mean “show the target in the viewport”; it produces a tall image of the page. For details on screenshot options and image formats, see the Playwright screenshot documentation.
Wait for the right page state
Pages with client-rendered content, authentication, lazy-loaded images, or embedded widgets may not be ready when the initial document loads. Waiting for the target heading to become visible is a useful baseline, but the right readiness signal depends on the page.
- If the heading appears before its data, wait for a selector that signals the finished content, or check for the expected text or value before capture.
- If scrolling triggers lazy loading, scroll the target into view and then wait for the relevant image or content to appear.
- If the section is inside a nested scrollable panel, make sure your locator targets the content in that panel. Playwright’s locator scrolling can account for nested scrollable containers; if the result is wrong, inspect the panel and scroll the intended context deliberately.
- Use a delay only when the page offers no stronger signal. A fixed wait can be too short on a slow run and unnecessarily long on a fast one.
Run the script on a schedule
The scheduler is a separate part of the workflow: it starts your script; the browser script performs navigation, scrolling, and capture. A GitHub Actions example is documented by the shot-scraper project, which also provides a template repository for scheduled screenshot automation. The precise configuration depends on the runner you choose, so check that provider’s current official documentation before relying on a particular schedule format or limit.
When comparing scheduling options, check whether they support your recurrence and timezone, can install and run a browser, handle secrets safely if the page requires sign-in, store the resulting files where you need them, retain artifacts for long enough, report failures, and fit your cost requirements. Provider schedules, quotas, artifact retention, and alerting are not interchangeable; confirm them for your selected environment.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #3
Keep recurring captures comparable
- Use the same browser setup and viewport dimensions on each run.
- Keep the URL, target locator, and capture type consistent unless the page structure changes.
- Use filenames that identify the page or section and capture time; the example creates an ISO timestamp in each filename.
- Decide where captures should persist. A file written by a scheduled job may need to be uploaded or stored separately if the runner does not retain it.
- Make failures visible: retain useful logs or configure the runner to notify you when the browser exits unsuccessfully.
These practices reduce avoidable variation, but they do not guarantee identical pixels: the site can change, and the cited browser documentation does not promise pixel-identical captures across machines.
Use Puppeteer if it fits your JavaScript project
Puppeteer is another option for JavaScript users already using that ecosystem. Its official guide covers page screenshots and element screenshots; it also attempts to scroll a hidden element into view when taking an element screenshot. Here is a compact viewport-capture example using a heading locator:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com/report', { waitUntil: 'domcontentloaded' });
const heading = page.locator('h2').filter({ hasText: 'Monthly results' });
await heading.wait();
await heading.scrollIntoView();
const timestamp = new Date().toISOString().replaceAll(':', '-');
await page.screenshot({ path: `monthly-results-${timestamp}.png` });
} finally {
await browser.close();
}
Confirm the locator methods against the Puppeteer version used in your project. To capture only an element, use the element screenshot API described in the Puppeteer screenshot guide. Choose between Playwright and Puppeteer based on your existing project and how you prefer to express robust locators; both support page and element captures, while the cited Playwright guides specifically explain scroll positioning for screenshots.
Troubleshoot missed or unreliable captures
The script times out waiting for the target
The text or locator may not match, the section may be behind authentication, or the site may have changed its markup. Check the actual heading text and inspect the page’s accessible structure. Prefer a unique role and name, a stable test attribute, or a deliberate CSS selector over a positional selector such as “the third heading.”
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsRank #4
The screenshot shows the wrong part of the page
Check that the locator identifies the intended section and that the capture call matches your goal. A page screenshot captures the current viewport; an element screenshot crops to the matched element; a full-page screenshot captures the entire document. For nested scrolling, verify that the target is in the expected scrollable panel.
The section is present but its content is blank or incomplete
Wait for a page-specific readiness condition, not merely initial navigation. Dynamic data, images loaded on scroll, and third-party content can arrive later. Add a wait for the content that matters, and inspect the resulting image when the site’s behavior changes.
Scheduled runs fail although local runs work
Compare the scheduled runner’s browser installation, environment, credentials, network access, and output path with your local setup. If the page requires authentication, store credentials through the runner’s secret mechanism rather than placing them in source code. Check the job logs and make sure the destination for screenshots exists and is writable.
Repeated screenshots differ
Confirm the viewport, browser setup, page state, and capture type are held constant. Differences can also come from changes to the website or content that updates between runs; a fixed browser configuration cannot freeze a live page.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Best Value
Or skip the browser setup
If you want an API call rather than maintaining a browser script and scheduled runner, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns an image or PDF; the API documentation is at ScreenshotNeo docs.
curl -G "https://api.screenshotneo.com/v1/shot"
-d access_key=YOUR_API_KEY
--data-urlencode url=https://example.com/report
-o shot.webp
The API call captures the page URL; this example does not itself schedule recurring captures or scroll to a selector. You still need a scheduler to repeat a request, and confirm the API options in the docs for the exact capture behavior you need. ScreenshotNeo accepts and removes known cookie-consent banners, newsletter popups, and chat widgets before capture, with each step able to be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
Frequently Asked Questions
Can I schedule captures in a specific timezone?
That depends on the scheduler you choose; check its current documentation for timezone support and how recurrence times are interpreted.
Can scheduled screenshots capture a page that requires login?
Yes, if the automation can authenticate in its runtime. Use the scheduler’s secret-handling mechanism for credentials and avoid embedding them in the script.
Will screenshots from different machines be pixel-identical?
No such guarantee is established by the cited browser documentation. The page itself can change, and browser and machine differences can affect output.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

