# Bulk File & Image Downloader (`cyber1nj3ct0r/bulk-file-downloader`) Actor

Download files and pictures in bulk: paste file links, or give web pages and get every picture, PDF, video or other file on them. Each file is stored with a shareable link, its size, type and SHA-256, plus an optional ZIP of everything.

- **URL**: https://apify.com/cyber1nj3ct0r/bulk-file-downloader.md
- **Developed by:** [Sanira Botheju](https://apify.com/cyber1nj3ct0r) (community)
- **Categories:** Developer tools, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 files

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Bulk File & Image Downloader do?

It downloads files in bulk and stores each one in your Apify storage with a link you can open or share. Give it either:

- **File addresses**: direct links to pictures, PDFs, spreadsheets, videos or any other file. Paste them, or link a text file or a Google Sheet that lists them.
- **Pages to collect files from**: ordinary web pages. The tool reads each page, finds its pictures (also the large version in `srcset`, lazy-loaded pictures and the page's preview image), documents, audio, video or archives, and downloads them.

For every file you get the stored file's link, its name, type, size, SHA-256 checksum and, for pictures, the width and height. Tick **Also pack all files into one ZIP** to get everything in a single `files.zip` as well.

### What data do you get?

| Field | What it holds |
|---|---|
| `fileUrl` | Link to the stored file; it opens without logging in to Apify |
| `fileName`, `fileKey` | The file's name, and its key in the run's key-value store |
| `contentType`, `bytes` | The type the server gave (for example `image/png`) and the size in bytes |
| `width`, `height` | Picture size in pixels |
| `sha256` | Checksum, to find duplicates or check a file later |
| `url`, `finalUrl`, `foundOn` | The address, where it redirected, and the page it was found on |
| `status`, `error` | `downloaded`, or `failed` with a code such as `HTTP_404`, `FILE_TOO_LARGE`, `NOT_A_FILE` or `TIMEOUT` |

The run summary (`SUMMARY` in the key-value store) counts what was downloaded and failed, lists each page with the number of files found on it, and links the ZIP.

### How to download files in bulk

1. Paste your file links under **File addresses**, or your pages under **Pages to collect files from** (or both).
2. For pages, choose the kinds of files under **Files to collect from pages**: pictures are chosen by default.
3. Press **Start**. Open the **Files** tab of the run and click the links, or download the ZIP from the summary.

### How much does it cost to download files?

You pay per file, plus a small amount for large files, because moving data costs money:

| Plan | Per file | Per megabyte above a file's first |
|---|---|---|
| Free and Starter | $0.50 per 1,000 files | $0.30 per GB ($0.0003 per MB) |
| Scale | $0.43 per 1,000 files | $0.27 per GB |
| Business | $0.35 per 1,000 files | $0.25 per GB |

Each file includes its first megabyte; every started megabyte after that costs $0.0003 (1 MB is 1,000,000 bytes). Examples at the Free and Starter price:

| What you download | Cost |
|---|---|
| 1,000 product pictures of 300 KB each | $0.50 |
| 100 PDFs of 2.5 MB each | $0.11 |
| One 100 MB video | $0.03 |

An address that cannot be downloaded (a 404, a timeout, a file over your size limit) is one result too and costs the price of one file. Apify's free plan gives $5 of credit each month, enough for about 10,000 small pictures. Set a maximum cost for the run, and the tool stops before it would go over it, also in the middle of large files.

### Input

```json
{
    "urls": [
        { "url": "https://apify.com/favicon.ico" },
        { "url": "https://crawlee.dev/img/crawlee-light.svg" }
    ],
    "pageUrls": [{ "url": "https://crawlee.dev/" }],
    "fileTypes": ["images", "documents"],
    "maxFilesPerPage": 100,
    "maxFileSizeMb": 50,
    "zip": true
}
```

More options: other file endings to collect from pages (`extensions`, for example `["dwg", "stl"]`), only files on the page's own site (`sameSiteOnly`), files in all (`maxFiles`), downloads at the same time in all and per website, the time limit per file, and the User-Agent.

### Output example

```json
{
    "url": "https://crawlee.dev/img/crawlee-light.svg",
    "position": 2,
    "foundOn": null,
    "status": "downloaded",
    "httpStatus": 200,
    "finalUrl": null,
    "contentType": "image/svg+xml",
    "fileName": "crawlee-light.svg",
    "fileKey": "00002-crawlee-light.svg",
    "fileUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/00002-crawlee-light.svg",
    "bytes": 6365,
    "extraMegabytes": 0,
    "sha256": "192e40bd55d97abcb3e1c562d17bf98b5997654209724165ffa02377477ed89a",
    "width": 106,
    "height": 28,
    "inZip": null,
    "timeMs": 758,
    "downloadedAt": "2026-10-16T14:54:34.238Z",
    "error": null
}
```

### What can you use it for?

- Save every picture of your own shop or website, for a backup or a move to a new platform.
- Turn a spreadsheet column of picture or document links into stored files with checksums and sizes.
- Collect the PDFs, price lists or manuals linked from a page you are allowed to use.
- Feed pictures to an AI or image pipeline, with the size and type of each one known in advance.
- Check that file links still work: failed downloads come with the HTTP status and the reason.

### Use it from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/cyber1nj3ct0r~bulk-file-downloader/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": [{"url": "https://apify.com/favicon.ico"}]}'
```

The same works from Python, JavaScript, Make, Zapier and n8n through Apify's integrations. Each result row holds `fileUrl`; the files can also be fetched from the run's key-value store by `fileKey`.

### FAQ

#### Which files does it find on a page?

Pictures: every `<img>` (the largest size in `srcset`, else the lazy-loading address such as `data-src`, else `src`), `<picture>` sources, the page's preview image for social sites, its icons and video posters. Video and audio: the page's `<video>` and `<audio>` sources. Documents, archives and the endings you add: links whose address ends with that file ending. Pictures drawn by style sheets or loaded later by scripts are not seen, because the tool reads the page's HTML without running it.

#### Does it respect robots.txt?

Yes, for pages and for the files found on them: what a site's robots.txt does not allow is skipped and counted in the summary. Addresses you list under **File addresses** are downloaded as given, like a browser would.

#### A site blocks the tool. What can I do?

The tool says who it is in its User-Agent and does not get round blocks, logins, paywalls or robot checks, and it uses no proxies. If a site refuses it, the result says so with the HTTP status. Only download files you have the right to use.

#### Can it download videos from YouTube, Instagram or TikTok?

No. It downloads files that sit at their own address and the files of ordinary web pages; it does not take videos out of streaming or social sites.

#### What happens to very large files?

They are written to disk as they come in, never held in memory, so the size of a file does not need more memory. Files above **Largest file** (50 MB by default, up to 2,000 MB) are not downloaded. When a server does not say how big a file is, the download stops at that size and the part already downloaded is counted.

#### Where are the files, and for how long?

In the run's key-value store, next to the results. Apify deletes a run's storage once your plan's data retention period has passed (on the free plan, the 10 most recent runs are kept for 4 months), so download or move the files you want to keep. The ZIP is limited by the run's disk space, which is twice its memory: for a very large ZIP, give the run more memory.

#### Something does not work

Open an issue on the tool's **Issues** tab with the run's link. Issues are answered.

# Actor input Schema

## `urls` (type: `array`):

Direct links to files, for example <code>https://www.example.com/report.pdf</code> or a picture's address. Add them one by one, paste many at once with <b>Bulk edit</b>, or link a text file (or a Google Sheet published as CSV) that holds them. Each address is downloaded once, as given.

## `pageUrls` (type: `array`):

Web pages whose pictures and files you want. The tool reads each page, finds the files of the kinds chosen below (also the large version of pictures in <code>srcset</code> and lazy-loaded pictures) and downloads them. Pages, and the files found on them, are read only where the site's robots.txt allows it.

## `fileTypes` (type: `array`):

Which files to take from the pages. Pictures include the page's preview image and icons; the other kinds are recognised by their file ending (.pdf, .mp3, .mp4, .zip and so on) or by the video and audio tags of the page.

## `extensions` (type: `array`):

More file endings to collect from pages, for example <code>dwg</code> or <code>stl</code>, without the dot.

## `sameSiteOnly` (type: `boolean`):

Skip files that sit on other sites, for example pictures on an image service or a shop's CDN. Off by default, because many sites keep their pictures elsewhere.

## `maxFilesPerPage` (type: `integer`):

At most this many files are taken from each page, in the order they appear on it.

## `maxFiles` (type: `integer`):

At most this many files are downloaded in one run, the listed addresses first. Your spending limit for the run also stops it.

## `maxFileSizeMb` (type: `integer`):

Files larger than this are not downloaded. When a server does not say how big a file is, the download stops at this size. 1 MB is 1,000,000 bytes.

## `zip` (type: `boolean`):

Adds <code>files.zip</code> with every downloaded file to the run's storage, linked from the run summary. Disk space is twice the run's memory: give the run more memory for very large ZIPs.

## `maxConcurrency` (type: `integer`):

How many files are downloaded at once in all.

## `perHostConcurrency` (type: `integer`):

How many files of the same website are downloaded at once. Keep it low for sites you do not run.

## `requestTimeoutSecs` (type: `integer`):

How long one download may take, from the request to the last byte.

## `userAgent` (type: `string`):

The name the tool sends with each request. Leave empty to use the tool's own name, which tells site owners what is visiting. Set your own only for sites you run or have permission to use.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://apify.com/favicon.ico"
    },
    {
      "url": "https://crawlee.dev/img/crawlee-light.svg"
    },
    {
      "url": "https://blog.apify.com/assets/images/og-default.png"
    }
  ],
  "pageUrls": [
    {
      "url": "https://crawlee.dev/"
    }
  ],
  "fileTypes": [
    "images"
  ],
  "sameSiteOnly": false,
  "maxFilesPerPage": 100,
  "maxFiles": 1000,
  "maxFileSizeMb": 50,
  "zip": false,
  "maxConcurrency": 8,
  "perHostConcurrency": 4,
  "requestTimeoutSecs": 120
}
```

# Actor output Schema

## `files` (type: `string`):

One record per file with its link, name, type, size, SHA-256 and picture size, or the reason it failed.

## `storedFiles` (type: `string`):

The run's key-value store, which holds every downloaded file (and files.zip when asked for).

## `summary` (type: `string`):

Counts for the run (downloaded, failed, bytes, pages read), each page with the number of files found on it, and the ZIP's link.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        {
            "url": "https://apify.com/favicon.ico"
        },
        {
            "url": "https://crawlee.dev/img/crawlee-light.svg"
        },
        {
            "url": "https://blog.apify.com/assets/images/og-default.png"
        }
    ],
    "pageUrls": [
        {
            "url": "https://crawlee.dev/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cyber1nj3ct0r/bulk-file-downloader").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": [
        { "url": "https://apify.com/favicon.ico" },
        { "url": "https://crawlee.dev/img/crawlee-light.svg" },
        { "url": "https://blog.apify.com/assets/images/og-default.png" },
    ],
    "pageUrls": [{ "url": "https://crawlee.dev/" }],
}

# Run the Actor and wait for it to finish
run = client.actor("cyber1nj3ct0r/bulk-file-downloader").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    {
      "url": "https://apify.com/favicon.ico"
    },
    {
      "url": "https://crawlee.dev/img/crawlee-light.svg"
    },
    {
      "url": "https://blog.apify.com/assets/images/og-default.png"
    }
  ],
  "pageUrls": [
    {
      "url": "https://crawlee.dev/"
    }
  ]
}' |
apify call cyber1nj3ct0r/bulk-file-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cyber1nj3ct0r/bulk-file-downloader"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/JbXdUwx9x8TUvNv72/builds/7GUsJF2APPfKEaFOo/openapi.json
