How to Take Bulk Website Screenshots from a CSV Using ScreenshotAPI
Prepare a CSV, upload it through ScreenshotAPI’s dashboard or API, track the batch, and retrieve screenshots with per-URL status and errors.
To take bulk website screenshots from a CSV using ScreenshotAPI, prepare a CSV with a url column containing complete HTTPS URLs, then upload it in the ScreenshotAPI dashboard or send it as multipart form data to its CSV upload endpoint. Track the returned job, then download the processed CSV with each URL’s status, screenshot link, and any error message. ScreenshotAPI documents CSV bulk capture as a paid-tier feature.
1. Prepare the CSV
Use a header row with url spelled exactly as shown. Put one fully qualified https:// URL on each row. Do not use a bare domain or omit the scheme.
url,file_type,width,height,fresh
https://example.com,png,1200,800,true
https://example.org,jpg,1440,900,false
The optional columns shown in ScreenshotAPI’s documentation let you configure captures per row. Add only what you need:
| Column | Purpose | Practical note |
|---|---|---|
file_type |
Output format, such as PNG, JPG, or PDF | Use a format accepted by your account and capture setup. |
width, height |
Viewport dimensions | Choose dimensions that match the layout you need to inspect. |
css |
Inject CSS into the page | Keep CSV quoting valid if the CSS contains commas or quotes. |
delay |
Wait in milliseconds before capture | Useful when the page fills in content after its initial load. |
headers |
Send custom request headers | Protect credentials if headers contain secrets. |
fresh |
Request a fresh capture in the documented examples | The documentation examples include this field; confirm accepted values for your account. |
These examples follow the vendor’s documented column names and examples; ScreenshotAPI does not guarantee every option combination for every account tier in the reviewed documentation. Check the current [ScreenshotAPI bulk CSV documentation](https://screenshotapi.net/documentation/bulk-screenshot) for the accepted schema and account requirements before a production run.
2. Choose how to submit the batch
There are two documented routes. The dashboard is convenient for a one-off manual batch. The API is suitable when a script or scheduled process needs to submit the same workflow repeatedly.
| Route | Use it when | Progress and output |
|---|---|---|
| Dashboard upload | You are submitting a batch manually. | View pending and completed URLs in the dashboard, then download the processed CSV there. |
| CSV upload API | You want to automate submission or status checks. | Poll the documented status endpoint and retrieve the output through the API. |
3. Upload the CSV with cURL
The documented endpoint accepts a multipart upload, with the file in the csv form field and the token in the query string. Replace the placeholder token with your account token and keep it out of source control and shared logs.
curl -X POST \
'https://api.screenshotapi.net/v1/bulk/csv?token=YOUR_TOKEN' \
-F 'csv=@sites.csv;type=text/csv'
Save the response: the API returns information needed to identify and monitor the submitted job. Keep the raw response while integrating, since the precise response fields can change.
4. Upload the CSV with Python
This runnable example posts sites.csv using the documented multipart field name. It prints the HTTP status and response body so you can inspect the job details returned by the service.
import os
import requests
TOKEN = os.environ["SCREENSHOTAPI_TOKEN"]
endpoint = "https://api.screenshotapi.net/v1/bulk/csv"
with open("sites.csv", "rb") as csv_file:
response = requests.post(
endpoint,
params={"token": TOKEN},
files={"csv": ("sites.csv", csv_file, "text/csv")},
timeout=120,
)
response.raise_for_status()
print(response.text)
Set the environment variable before running, for example export SCREENSHOTAPI_TOKEN='your-token' in a POSIX shell. A long client timeout does not extend any server-side processing deadline; it only controls how long the upload request waits for a response.
5. Upload the CSV with Node.js
Node.js 18 and later include fetch, FormData, and Blob. This example reads the CSV, sends it as multipart form data, and prints the response.
import { readFile } from "node:fs/promises";
const token = process.env.SCREENSHOTAPI_TOKEN;
if (!token) throw new Error("Set SCREENSHOTAPI_TOKEN first");
const csv = await readFile("sites.csv");
const form = new FormData();
form.append("csv", new Blob([csv], { type: "text/csv" }), "sites.csv");
const endpoint = new URL("https://api.screenshotapi.net/v1/bulk/csv");
endpoint.searchParams.set("token", token);
const response = await fetch(endpoint, { method: "POST", body: form });
const body = await response.text();
if (!response.ok) {
throw new Error(`Upload failed (${response.status}): ${body}`);
}
console.log(body);
Do not set the multipart Content-Type header yourself when using FormData; the runtime adds the boundary that separates the file part.
6. Monitor the job and retrieve results
For a dashboard submission, use the dashboard’s progress view and download the processed CSV when it is ready. For an API submission, use the job UUID returned from upload with ScreenshotAPI’s documented CSV status endpoint. The status response includes progress information such as percentage complete, successful URLs, and failed URLs. When finished, download the processed CSV through the dashboard or the documented download endpoint. ScreenshotAPI also says it emails a download link when a batch is ready.
The returned CSV example includes url, status, screenshot, and error_message. Process rows individually rather than treating the whole batch as a single success or failure: retain successful screenshot links and route failed rows into a retry or review list. Open a small sample of output links to confirm the page, viewport, and timing are right for your use case.
Limits, timing, and cost
- CSV bulk availability: ScreenshotAPI’s help page says CSV bulk capture is available only on a paid tier. Confirm the current plan requirement in your account.
- Rate: The help page gives a general range of 20–80 requests per minute, depending on subscription. It does not describe this as a CSV row limit.
- Do not confuse API limits: The bulk documentation says the JSON bulk API supports up to 50 URLs at once. That stated limit is for the JSON API; the reviewed CSV documentation does not specify a CSV upload row cap.
- Completion time: Processing time depends on batch size and configuration complexity. The documentation gives no completion-time estimate, so avoid assuming a fixed duration.
- Retention: The help page describes screenshot storage up to 30 days on the free tier and six months on paid tiers, depending on TTL. Since the CSV feature is separately described as paid-tier only, verify the current retention behavior and account settings before building a workflow around stored links.
For larger jobs, submit in manageable batches, record each job identifier, and make your automation safe to resume. A batch is not complete until you have retrieved its output and accounted for failed rows.
Common errors and fixes
| Symptom | Likely cause | What to do |
|---|---|---|
| Upload is rejected or rows fail validation | Missing or misspelled url header, malformed row, or URL without a full HTTPS scheme. |
Check the header and validate every row as a complete https:// URL. Review the processed CSV’s error field. |
| Authentication failure | Missing, expired, or incorrect token. | Check the token and ensure the request includes it as the documented query parameter. Keep it secret. |
| API says the file is missing | The multipart field name differs from the required csv, or the file part was not attached. |
Use csv as the form field and confirm the path and filename. |
| Node upload fails with a multipart parsing error | A manually set Content-Type omitted the required boundary. |
Let fetch create the multipart header when sending FormData. |
| Some pages are blank, incomplete, or missing dynamic content | Pages may need more time to render or may fail to load in the capture environment. | Try the documented per-row delay where appropriate, then inspect the row’s status and error. The docs do not promise a fixed rendering time. |
| The batch seems to be taking a long time | Batch size and configuration complexity affect processing time. | Check the dashboard or status endpoint for progress; do not infer failure from elapsed time alone. |
| Some screenshot links no longer work | Stored images may have reached their configured retention period. | Download and retain outputs you need, and verify current TTL and plan behavior. |
Or skip the browser setup
If you want to automate screenshots without building browser infrastructure, ScreenshotNeo accepts a URL in one GET request and returns a PNG, JPEG, WebP, or PDF. For a CSV workflow, your script can read each row and call the endpoint once per URL; the API also supports bulk capture of up to 100 URLs per call.
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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before capture; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up free for ScreenshotNeo.
FAQ
Does the CSV need a particular filename?
The reviewed documentation specifies the multipart field name csv and a url column, not a required filename. Use a descriptive local filename and attach it under the required field.
Can I upload a CSV from a script?
Yes. The documented route is a multipart POST to the CSV bulk endpoint. Use the returned job details to check status and retrieve the processed file.
Does the 50-URL maximum apply to CSV uploads?
The stated 50-URL maximum applies to ScreenshotAPI’s JSON bulk API. The reviewed CSV instructions do not publish a CSV row maximum.
Can every row use different capture settings?
The documentation describes optional CSV columns for settings such as format, dimensions, CSS, delay, and headers. Confirm the currently accepted columns and values for your account before relying on a particular combination.
Sources
- ScreenshotAPI bulk screenshot documentation — CSV preparation, upload, status, output, and the separate JSON API limit.
- ScreenshotAPI help — paid-tier CSV availability, general request rate, and storage retention details.


