Capture the page in a browser, then upload the screenshot bytes to Amazon S3. For an agent running in a trusted server-side worker, use the AWS SDK with narrowly scoped role credentials. If the browser or agent client should not receive AWS credentials, have a trusted backend create a short-lived presigned PUT URL for a specific bucket key and let the agent upload the image to it.
Separate screenshot capture from S3 upload
The workflow has two distinct steps: browser automation renders and captures the website; an upload step stores the resulting file or bytes as an S3 object. Playwright’s documented flow navigates to a page and saves a screenshot with page.screenshot(). The screenshot can also be captured as bytes, which is useful when passing it directly to an AWS SDK upload call. See Playwright’s Page screenshot API.
As an Amazon Associate I earn from qualifying purchases.
- Start or connect to a browser session.
- Navigate to the target URL and wait for the page state your workflow requires.
- Capture the viewport, a selected element, or the full page.
- Upload the resulting file or bytes using either server-side AWS credentials or a presigned PUT URL.
- Record the capture result and object key without logging credentials or presigned URLs.
The examples below use Node.js, Playwright, and the AWS SDK for JavaScript v3. Install the packages in your project with npm install playwright @aws-sdk/client-s3. Install the browser binaries as required by your Playwright environment. Configure AWS credentials for the trusted runtime using your deployment’s normal role or credential-provider setup; do not hard-code access keys in source code.
Choose where the upload runs
Trusted agent runtime: upload with the AWS SDK
Use this pattern when the agent runs in a trusted backend or worker that can obtain AWS credentials, such as credentials from an execution role. Grant the role only the S3 actions and object scope this workflow needs. The exact policy depends on your bucket and encryption setup; there is no single policy appropriate for every deployment.
#1 Best Overall
- Do what you love, uninterrupted — 25% faster performance than the previous generation and is ideal for seamless streaming, reading, and gaming.
- High-def entertainment — A 10.1" 1080p Full HD display brings brilliant color to all your shows and games. Binge watch longer with 13-hour battery, 3 or 4 GB RAM, 32 or 64 GB of storage, and up to 1 TB expandable storage with micro-SD card (sold separately).
- Thin, light, durable — Tap into entertainment from anywhere with a lightweight, durable design and strengthened glass made from aluminosilicate glass. As measured in a tumble test, Fire HD 10 is 2.7 times as durable as the Samsung Galaxy Tab A8 (2022).
- Stay up to speed — Use the 5 MP front-facing camera to Zoom with family and friends, or create content for social apps like Instagram and TikTok.
- Ready when inspiration strikes — With 4,096 levels of pressure sensitivity, the Made for Amazon Stylus Pen (sold separately) offers a natural writing experience that responds to your handwriting. Use it to write, sketch in apps like OneNote, and more.
import { chromium } from 'playwright';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { randomUUID } from 'node:crypto';
const bucket = process.env.S3_BUCKET;
const region = process.env.AWS_REGION;
const targetUrl = 'https://example.com';
if (!bucket || !region) {
throw new Error('Set S3_BUCKET and AWS_REGION');
}
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 30_000 });
await page.locator('body').waitFor({ state: 'visible', timeout: 10_000 });
const image = await page.screenshot({ type: 'png', fullPage: true });
const key = `screenshots/${randomUUID()}.png`;
const s3 = new S3Client({ region });
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: key,
Body: image,
ContentType: 'image/png'
}));
console.log(JSON.stringify({ targetUrl, key, contentType: 'image/png', uploaded: true }));
} finally {
await browser.close();
}
This saves a full-page PNG under a run-unique key and sends the screenshot bytes directly to S3. For a viewport-only capture, remove fullPage: true. For JPEG or WebP, change the screenshot type, file extension, and matching ContentType. If you use a stream or file instead of the in-memory buffer, pass that body to the SDK upload operation and handle the file lifecycle in your runtime.
Untrusted browser or client: upload with a presigned PUT URL
When the browser, desktop client, or isolated agent should not receive AWS credentials, a trusted backend can generate a short-lived presigned URL for one intended object key and return the URL to the uploader. AWS describes presigned URLs as a way to grant time-limited object access without changing the bucket policy: Amazon S3 presigned URL documentation.
Generate the URL on a trusted server using credentials allowed to perform the intended upload. The backend—not an untrusted client—should decide the bucket and key. The following is the essential server-side pattern with the AWS SDK for JavaScript v3; pass the resulting URL only to the authorized uploader:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { randomUUID } from 'node:crypto';
const s3 = new S3Client({ region: process.env.AWS_REGION });
const bucket = process.env.S3_BUCKET;
export async function createScreenshotUploadUrl() {
const key = `screenshots/${randomUUID()}.png`;
const command = new PutObjectCommand({
Bucket: bucket,
Key: key,
ContentType: 'image/png'
});
const url = await getSignedUrl(s3, command, { expiresIn: 300 });
return { url, key, contentType: 'image/png' };
}
The agent captures the screenshot and uploads the bytes using the signed method and content type:
import { chromium } from 'playwright';
const upload = await fetch('https://your-trusted-backend.example/screenshot-upload', {
method: 'POST'
});
if (!upload.ok) throw new Error(`Could not request upload URL: ${upload.status}`);
const { url, key, contentType } = await upload.json();
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded', timeout: 30_000 });
const image = await page.screenshot({ type: 'png', fullPage: true });
const result = await fetch(url, {
method: 'PUT',
headers: { 'Content-Type': contentType },
body: image
});
if (!result.ok) throw new Error(`S3 upload failed: ${result.status} ${await result.text()}`);
console.log(JSON.stringify({ key, uploaded: true }));
} finally {
await browser.close();
}
This illustrative endpoint must be implemented by your trusted backend and protected according to your application’s authentication and authorization requirements. Do not accept arbitrary bucket names or keys from a client and sign them without validation.
Rank #2
- Fire HD 8 offers an 8" HD display for seamless streaming and gaming, coupled with a 5MP rear facing camera for photos—with a thin, light, durable design.
- Fast and responsive with long battery life - With up to 4 GB RAM (2X more than 2022 release), 64GB of storage, and up to 1 TB of expandable storage (sold separately). Hexa-core processor for fast, responsive performance. Up to 13 hours of reading, browsing the web, watching videos, gaming, and listening to music at home and on-the-go.
- Save time, get creative - Enjoy three smart tools to help you send polished emails, quickly summarize webpages, and create unique wallpapers.
- Stream or download your favorite shows, movies, and games (like Minecraft, Roblox, and more). Enjoy your favorite content from Facebook, Hulu, Instagram, TikTok, and more through Amazon’s Appstore (Google Play not supported. Subscription for some apps required).
- Stay connected with family and friends - ask Alexa to make video calls to friends and family or download apps like Zoom.
How the two patterns differ
| Consideration | Agent runtime SDK upload | Backend-minted presigned PUT |
|---|---|---|
| Where AWS credentials live | In the trusted server-side runtime, ideally as role credentials. | Only in the trusted signer; the uploader receives a temporary URL. |
| Best fit | A backend worker that is trusted to access S3. | A browser or isolated client that should not receive AWS credentials. |
| Additional setup | Role permissions scoped to the required bucket and object prefix. | A signing endpoint, expiry handling, and exact request method and headers. |
| Browser CORS | Not needed for server-to-server SDK uploads. | Required if the PUT is sent from a browser origin; not required for a server-side uploader. |
Make keys, headers, and access deliberate
Use unique keys when preserving history
An S3 upload to an existing key replaces that object. Use a run ID, timestamp, or unique identifier in keys such as screenshots/<run-id>/<timestamp>.png when you want to keep each capture. Reuse a fixed key only when replacement is intentional.
Match the signed request exactly
For a presigned upload, use the HTTP method for which the URL was signed, preserve the URL unchanged, and send any headers that were included in signing—especially Content-Type when it was signed. A changed request, expired URL, wrong region, or inadequate signer permission can prevent the upload. Temporary credentials used to create the URL can also expire before the configured URL lifetime, so the URL cannot remain valid beyond those credentials.
Protect the URL and screenshot data
- Treat a presigned URL as a bearer credential: anyone who obtains it can exercise its delegated capability until it expires, subject to the signer’s permissions.
- Keep URLs short-lived and out of logs, analytics, and user-visible content unless sharing is intended.
- Choose bucket access controls, retention, encryption, and any screenshot-redaction steps to match the sensitivity of the pages being captured.
- Log the target URL, capture time, object key, content type, and upload outcome separately from secrets.
Handle browser-origin uploads and managed browsers
Configure CORS only for browser-to-S3 requests
If JavaScript running on a website uploads directly to S3, configure the bucket’s CORS policy for the application origin, the required PUT method, and request headers such as Content-Type. CORS controls whether a browser permits the cross-origin request; it does not grant S3 authorization. A server-side agent upload does not use browser CORS. See AWS’s direct-upload and CORS example; check current AWS SDK guidance for the exact syntax used by your application.
Use a managed browser only when the workflow needs one
A local Playwright browser is sufficient for ordinary page navigation and screenshots. AWS describes AgentCore Browser’s WebSocket/CDP interface as compatible with standard browser automation libraries including Playwright. Its separate InvokeBrowser path addresses OS-level actions such as native dialogs and desktop screenshots, which go beyond a page screenshot. An AWS reference architecture uses Playwright with AgentCore Browser, stores screenshots and session transcripts in S3, and streams a presigned URL to the UI so screenshot bytes travel from S3 to the viewer rather than through the WebSocket: AWS browser-agent reference architecture.
Troubleshoot failed captures and uploads
| Symptom | Likely cause | What to check |
|---|---|---|
| Navigation times out or the page is incomplete | The page is slow, blocked, or the chosen load condition does not match its behavior. | Check the target URL and browser logs; choose a wait condition suited to the site, or wait for a specific visible selector instead of assuming the page is ready at navigation completion. |
| Screenshot is blank or missing lazy-loaded content | The relevant content has not rendered or loaded before capture. | Wait for a page-specific element or state before calling the screenshot API. For full-page capture, verify that the site’s lazy-loaded regions have been triggered as needed. |
AccessDenied or an authorization failure |
The runtime role or URL signer lacks permission, or a bucket policy denies the request. | Check the caller’s permissions, bucket and key, region, and applicable bucket policy. Keep permissions limited to the needed operation and object scope. |
| Presigned PUT returns a signature or request error | The URL expired, the request method or signed headers changed, the region is wrong, or the URL was altered. | Request a fresh URL, use PUT, copy the URL unchanged, and send the same content type used to create the signature. |
| Browser reports a CORS error | The bucket CORS configuration does not allow the requesting origin, method, or headers. | Adjust the bucket CORS rules for the actual browser origin, PUT, and headers. Confirm that S3 authorization is also valid; CORS does not replace it. |
| New capture overwrites an older one | The upload reused the same object key. | Generate a unique key for each capture, or use a stable key only when replacement is desired. |
| Object is not visible where expected | The key prefix, bucket, or region differs from the expected location, or the upload was not confirmed. | Record the returned key and upload outcome. If the workflow requires confirmation, perform a HEAD request or verify a checksum after upload; AWS supports checksums for SigV4 presigned uploads. |
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its one-call API returns a screenshot or PDF, so you can avoid running and maintaining browser capture code for this step. The API accepts a URL and can return PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for request options.
Rank #3
- Like-New Amazon Fire HD 8 tablet is refurbished, tested, and certified to look and work like new and comes with the same limited warranty as a new device. Like-New Amazon devices may be packaged in generic Amazon-branded boxes.
- Fire HD 8 offers an 8" HD display for seamless streaming and gaming, coupled with a 5MP rear facing camera for photos—with a thin, light, durable design.
- Responsive with all day battery life - Includes 3GB RAM (50% more than 2022 release), 32GB of storage, and up to 1 TB of expandable storage (sold separately). Up to 13 hours of reading, browsing the web, watching videos, gaming, and listening to music at home and on-the-go.
- Save time, get creative - Enjoy three smart tools to help you send polished emails, quickly summarize webpages, and create unique wallpapers.
- Stream or download your favorite shows, movies, and games (like Minecraft, Roblox, and more). Enjoy your favorite content from Facebook, Hulu, Instagram, TikTok, and more through Amazon’s Appstore (Google Play not supported. Subscription for some apps required).
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
To put that returned file in S3 from a trusted Node.js worker, use the AWS SDK upload pattern above with Body set to the downloaded response bytes. For a client without AWS credentials, upload those bytes to a backend-issued presigned PUT URL instead. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, with response headers indicating the page verdict and billing status. Its MCP server gives AI agents tools including take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.
Free tools Windows power users keep installed
One-click scans. No signup required.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
Frequently Asked Questions
Can an AI agent save a screenshot to S3 without receiving AWS credentials?
Yes. A trusted backend can mint a short-lived presigned PUT URL for a specific object key, then the agent can upload the image bytes using that URL.
Does S3 CORS apply to an agent running on a server?
No. Browser CORS applies to requests made by browser code. Server-to-server uploads using the AWS SDK do not use browser CORS.
Can I upload screenshots in formats other than PNG?
Yes. Playwright supports PNG, JPEG, and WebP screenshot output; make the S3 content type and object-key extension match the chosen format.
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.




