How to Schedule Website Screenshots of Pages Behind Basic Authentication
Schedule recurring screenshots of HTTP Basic Authentication pages with Playwright, secure credentials, and choose viewport or full-page captures.
To schedule screenshots of a page protected by HTTP Basic Authentication, run a browser automation script on a schedule. In Playwright, provide the username and password as httpCredentials on the browser context, navigate to the page, wait for the content you need, and save a viewport or full-page screenshot. The scheduler starts the job; it is separate from the authentication and capture code.
This guide uses Node.js and Playwright. If the page shows its own HTML login form instead of a browser-level username and password challenge, use an application login flow instead; the Basic Authentication example below will not sign in to that form.
1. Confirm which kind of authentication protects the page
HTTP Basic Authentication typically triggers a browser-level credentials challenge when the page or a protected resource is requested. For that case, pass credentials to the Playwright browser context. Set origin when you want to limit which origin receives those credentials.
A site may instead render a login page with username and password fields. That is an application authentication flow. Automate the form submission and any additional steps the site requires, or use Playwright’s saved browser state where suitable. Treat saved state as a secret: it can contain cookies and headers that let someone act as the authenticated user.
2. Create a scheduled screenshot script
Install Playwright and its browser in the environment that will run the job. Store the protected page URL, username, and password in environment variables provided by that environment’s secret store. Do not put credentials directly in source code or print them in logs.
npm init -y
npm install playwright
npx playwright install chromium
Save this as screenshot.mjs. It takes a viewport screenshot by default. Set FULL_PAGE=true for a full-page capture. Change READY_SELECTOR to a selector that appears when the page content you need is ready; if omitted, the script waits for the page load event, which may not mean that client-rendered content is finished.
import { chromium } from 'playwright';
const targetUrl = process.env.TARGET_URL;
const username = process.env.BASIC_AUTH_USERNAME;
const password = process.env.BASIC_AUTH_PASSWORD;
const outputPath = process.env.OUTPUT_PATH ?? 'screenshot.png';
if (!targetUrl || !username || !password) {
throw new Error('Set TARGET_URL, BASIC_AUTH_USERNAME, and BASIC_AUTH_PASSWORD.');
}
const browser = await chromium.launch({ headless: true });
try {
const context = await browser.newContext({
httpCredentials: {
username,
password,
// Optional: restrict credentials to this origin, e.g. 'https://example.com'.
origin: new URL(targetUrl).origin,
},
});
const page = await context.newPage();
const response = await page.goto(targetUrl, { waitUntil: 'load', timeout: 60_000 });
if (!response || !response.ok()) {
throw new Error(`Navigation failed${response ? ` with HTTP ${response.status()}` : ''}.`);
}
if (process.env.READY_SELECTOR) {
await page.locator(process.env.READY_SELECTOR).waitFor({ state: 'visible', timeout: 30_000 });
}
await page.screenshot({
path: outputPath,
fullPage: process.env.FULL_PAGE === 'true',
animations: 'disabled',
});
await context.close();
} finally {
await browser.close();
}
Run it locally by setting the environment variables in your shell or secret manager, then invoking node screenshot.mjs. Use a test page and non-production credentials while validating the job. Keep the output path in a location with access controls appropriate for the page’s contents.
3. Schedule the job
Scheduling is a separate operational choice. Run the script using your existing CI scheduler or a system scheduler on a maintained host. Choose based on whether the runner can reach the protected page, how it stores secrets, whether it retains logs and run history, how failures are reported, and where screenshot files are kept.
- Install Node.js, the project dependencies, and the Playwright Chromium browser on the runner.
- Configure the runner’s secret mechanism with
TARGET_URL,BASIC_AUTH_USERNAME, andBASIC_AUTH_PASSWORD. Avoid exposing values in command-line logs. - Set the schedule in the scheduler you use, and make its working directory the project directory so Node can find the installed dependencies.
- Choose an output retention and access policy. A screenshot of a protected page may contain sensitive information even though it does not contain the password.
- Arrange a failure notification or inspect the scheduler’s run history so missed captures do not go unnoticed.
The Playwright CI guide covers running browser automation in CI. The documentation reviewed for this article does not establish current schedule syntax for a specific provider, so use the scheduler’s current documentation for its trigger configuration.
4. Choose screenshot and wait settings
| Choice | Use it when | Notes |
|---|---|---|
| Viewport screenshot | You need a repeatable view of the visible browser area. | Default Playwright screenshot behavior; keep viewport dimensions stable between runs. |
| Full-page screenshot | You need the whole scrollable document. | Enable fullPage: true. Very long pages create larger files and can take longer to capture. |
| Readiness selector | The relevant content appears after navigation. | Wait for a site-specific element or state. There is no universal selector that proves every page is ready. |
| Load event | The page is mostly server-rendered or otherwise ready at load. | Additional client-side requests may still change the page after load. |
For recurring comparisons, keep the browser version, operating system, viewport, device scale, and headless setting as consistent as practical. Rendering can vary with operating system, browser version, settings, hardware, power source, and headless mode.
5. Protect credentials and captured pages
- Use the runner’s secret store for the Basic Authentication username and password. Do not commit them, place them in a screenshot filename, or log them.
- Keep Playwright authentication-state files out of version control. They can include cookies and headers that may be used to impersonate an account.
- Restrict access to screenshot artifacts and set a retention period suited to the data shown.
- Use only an account and page the job is authorized to access. Avoid sharing a credential-bearing URL or diagnostic log.
Playwright’s authentication guidance says: “We strongly discourage checking them into private or public repositories.”
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The screenshot shows a login prompt or a 401/403 page. | The target uses an HTML login form, credentials are incorrect, or the credentials were not sent to the protected origin. | Confirm the authentication type and credentials. For Basic Authentication, check the context’s httpCredentials and optional origin. For a form login, automate the form flow instead. |
| The navigation times out. | The host is slow or unreachable from the runner, the page never reaches the chosen load state, or a network boundary blocks access. | Check runner network access and the target URL. Use an appropriate timeout and wait for a specific readiness condition when the page continues loading background resources. |
| The capture is blank or missing dynamic content. | The screenshot ran before the page’s client-side content was ready. | Wait for a selector or application-specific ready condition before capture. Verify the selector exists after authentication. |
| The image differs between scheduled runs. | The browser environment, viewport, page data, or timing changed. | Keep browser and viewport settings stable and wait for deterministic page content. Some differences may come from live data or the rendering environment. |
| The scheduled job works locally but fails on the runner. | The runner lacks browser dependencies, secrets, network access, or the expected working directory. | Install Playwright’s browser for that runner, configure its secrets, verify protected-host reachability, and run from the project directory. |
| The output file is missing or inaccessible. | The output path is relative to a different working directory or the artifact location is not retained. | Set an explicit output path and configure the scheduler to retain or transfer that artifact securely. |
7. Performance, reliability, and cost
A scheduled browser launch and page render consume runner time and resources. Full-page captures generally involve more page area and produce larger files than viewport captures. Keep the page wait focused on the content you need, avoid unnecessarily frequent runs, and use a stable runner if visual comparison matters.
Reliability depends on the protected host, runner network access, credential rotation, browser installation, and the scheduler’s alerting and retry behavior. Handle non-success navigation responses as failures, retain enough run history to diagnose missed captures, and rotate secrets through the runner’s secret mechanism.
With a self-hosted or CI Playwright job, account for the compute and artifact storage supplied by that environment; the sources cited here do not establish a universal cost. A managed screenshot API can remove browser installation and job maintenance, but access to a Basic Authentication protected origin must be checked against that API’s supported authentication options before use.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Use its one-call capture for publicly accessible pages or pages supported by its request options; the facts available here do not establish Basic Authentication support, so confirm the relevant option in the API documentation before sending a protected URL.
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}`);
ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.
Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Can I use a normal login page with this Basic Authentication script?
No. A form-based login is an application flow. Automate the form and any required follow-up, or use saved authenticated browser state securely.
Should I capture the viewport or the full page?
Capture the viewport for a fixed visible area; use full-page capture when the entire scrollable document matters.
Where should I store the screenshot?
Use a restricted artifact store or directory with a retention period appropriate to the information on the protected page.


