How it works
There are two scenarios where ZenRows can return a file download:Direct file response
If the target URL returns the file directly in the HTTP response (for example, a direct link to a PDF or image), ZenRows fetches the file and returns it as binary content. This is the most reliable and straightforward method.
Triggered download via JS Instructions
If the download is triggered by a user action (such as clicking a button or link), you can use ZenRows JS Instructions to simulate that interaction. If the file download starts automatically after the action without prompting the user to choose a save location, ZenRows can capture and return the file.
Downloads are only possible when the file is delivered directly in the HTTP response. If the site asks the user to choose a download location or requires additional interaction after the trigger, ZenRows cannot capture the file. In those cases, use the Scraping Browser for more control over the browser session.
Basic usage
Pass the direct file URL as theurl parameter. ZenRows returns the binary content of the file, which you can then save to disk:
When to use file downloads
File download is the right approach when the content you need is a binary asset rather than scraped HTML. It works well for:- Product images: download images directly from e-commerce product pages or media libraries.
- PDFs and documents: collect downloadable reports, whitepapers, manuals, or invoices.
- Data exports: fetch CSV, JSON, or XML files served at direct URLs.
- Media assets: download audio or video files linked directly on a page.
For files that require navigating a page and triggering a download interaction, use JS Instructions to simulate the user action before the file is returned.
File size limits
ZenRows enforces a maximum file size per request to ensure stable performance across all plans. If the file you are trying to download exceeds your plan’s limit, the API returns a413 Content Too Large error.
You can find the file size limits for each plan on our Pricing Documentation.
Best practices
Save as binary, not text:All file downloads return binary content. Always write the response body in binary mode (for example,
"wb" mode in Python and Ruby, Buffer in Node.js, or FileOutputStream in Java). Writing binary content as text will produce a corrupt file.
Enable js_render for pages that load content dynamically: If the page loads content dynamically after the initial render, enable
js_render to ensure the full page is visible before the file is downloaded.
Enable premium_proxy for pages that are blocked by anti-bot systems: If the page is blocked by an anti-bot system, enable
premium_proxy to bypass the block.
Check the status code before saving: Always verify that the response returned a
200 status code before writing to disk. Saving an error response as a file will produce an unreadable or corrupt output.
Use direct file URLs where possible: Direct file URLs (ending in
.pdf, .jpg, .csv, etc.) are the most reliable download method. If you need to navigate to a page first to trigger the download, use JS Instructions to simulate the click and capture the resulting file.
Credits are charged on successful responses: File download requests are charged when the API returns a
200 status code, regardless of what the file contains. Test with a small set of URLs before running large download batches.
Troubleshooting
The downloaded file is corrupt or cannot be opened
The downloaded file is corrupt or cannot be opened
You are likely writing the response as text instead of binary. Make sure you are using binary write mode in your language of choice (
"wb" in Python and Ruby, Buffer in Node.js, FileOutputStream in Java) and writing the raw response body rather than a text representation of it. This applies to all binary file types including PDFs, images, and archives.The API returns HTML instead of the file
The API returns HTML instead of the file
This usually means the target URL returns a webpage rather than the file directly. Check that the URL you are passing points directly to the file (for example, ending in
.pdf or .jpg) rather than to a page that contains a download button or link. For page-triggered downloads, use JS Instructions to simulate the interaction.I receive a 413 Content Too Large error
I receive a 413 Content Too Large error
The file exceeds your plan’s maximum file size limit. Check the Pricing Documentation for the limit on your plan. For large files, consider whether you can access a compressed version or a lower-resolution asset from the same source.
The download is triggered by a button click and ZenRows returns nothing
The download is triggered by a button click and ZenRows returns nothing
Pricing
File download requests are included at no additional cost with all ZenRows requests. You only pay extra for JS Render and Premium Proxy when used.FAQ (Frequently Asked Questions)
What file types can ZenRows download?
What file types can ZenRows download?
ZenRows can download any file type that is returned directly in the HTTP response body, including PDFs, images (PNG, JPEG, WebP, GIF), CSVs, ZIPs, audio files, and video files. The API returns the raw binary content regardless of file type.
Do I need js_render=true to download files?
Do I need js_render=true to download files?
No, not for direct file URLs. If the URL points directly to a file, ZenRows fetches and returns it without needing a browser render. You only need
js_render=true if the file download is triggered by a JavaScript interaction on a page.Can I download multiple files in one request?
Can I download multiple files in one request?
No. Each ZenRows request targets a single URL and returns a single response. To download multiple files, send a separate request for each file URL. For high-volume downloads, use concurrent requests within your plan’s concurrency limits.
Can I download files that require authentication?
Can I download files that require authentication?
Yes. You can pass custom headers (such as
Authorization or session cookies) using the custom_headers parameter to authenticate with the target server before the file is returned. Another method is to use the JS Instructions to simulate the user action that triggers the download.What happens if the file exceeds the size limit?
What happens if the file exceeds the size limit?
The API returns a
413 Content Too Large error. The request is still counted toward your usage. Check your plan’s file size limit in the Pricing Documentation before downloading large files at scale.