# Erome Video Downloader (`datawatcher/erome-video-downloader`) Actor

Downloads the videos (.mp4) and images of erome.com albums, searches and creator profiles into your Apify storage, named albumId_mediaId.ext. Optional ZIP of all files and optional full details (views, likes, duration).

- **URL**: https://apify.com/datawatcher/erome-video-downloader.md
- **Developed by:** [DataWatcher](https://apify.com/datawatcher) (community)
- **Categories:** Videos
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 52.6% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.80 / 1,000 video file saveds

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

## Erome Video Downloader

**Download Erome videos and images in bulk**: scrape erome.com albums by keyword search, creator profile or album URL, get the data of each media file with **each file** saved in your run's Key-Value Store, and fetch it all through the Apify API. Album files are named **`{albumId}_{mediaId}.{ext}`** (for example `AlbumId1_MediaId1.mp4`), so the files of one album sit together. Every row has the link to the saved file. Get the rows as JSON, CSV or Excel.

- Saved file: `storedFile` (key, public link, size in bytes, type, status).
- File names: `{albumId}_{mediaId}.mp4` for videos and `{albumId}_{mediaId}.<ext>` for images, no folders, the same names inside `videos.zip`.
- The actor sends the header `Referer: https://www.erome.com/` for you, so the files are saved without a 403.
- Short rows by default (files first). Set `extractDetails` to `true` for the full row with tags, views and likes.
- Optional `videos.zip` with all saved files of the run (`createZip`).

Need only links and data, without files? Use the [Erome Video Scraper](https://apify.com/datawatcher/erome-scraper).

### ⭐ Why this one

> **1️⃣ One schema across video sites.**
> All our video actors share one output schema and one input schema. Build your pipeline once: our other video actors ([Erome Video Scraper](https://apify.com/datawatcher/erome-scraper), [Fikfap Video Scraper](https://apify.com/datawatcher/fikfap-scraper), [Redgifs Video Scraper](https://apify.com/datawatcher/redgifs-scraper), [Ultrathots Video Scraper](https://apify.com/datawatcher/ultrathots-scraper), [XFree Video Scraper](https://apify.com/datawatcher/xfree-scraper), [Fikfap Video Downloader](https://apify.com/datawatcher/fikfap-video-downloader), [RedGIFs Video Downloader](https://apify.com/datawatcher/redgifs-video-downloader), [Ultrathots Video Downloader](https://apify.com/datawatcher/ultrathots-video-downloader), [XFree Video Downloader](https://apify.com/datawatcher/xfree-video-downloader)) take the same input and return the same fields, so adding a site means changing the actor name, not your code.

- **Real files, one price.** $8.00 per 1,000 saved files, no start fee.
- **The header is handled.** erome.com files need `Referer: https://www.erome.com/`; the actor sends it, so you get the file, not an error.
- **Files named for you.** Every album file is `{albumId}_{mediaId}.{ext}`, so the media of one album sort together.
- **One ZIP of the run.** Turn on `createZip` and get `videos.zip` with all files under the same names.
- **Videos and images.** A video is saved as the `.mp4` in 720p, an image as the full-size picture; `mediaType` tells you which.
- **Free when nothing is saved.** Skipped and failed files cost nothing; their rows are still returned.

### 🔎 What it extracts

One row per media file (video or image) of an album, with its file saved. The page types it reads:

| Page type | Example URL | Input to use |
|---|---|---|
| Search | `https://www.erome.com/search?q=example+words` | `searchQueries` or `startUrls` |
| Tag | `https://www.erome.com/search?q=example` | `tags` or `startUrls` |
| Profile | `https://www.erome.com/CreatorName` | `usernames` or `startUrls` |
| Explore | `https://www.erome.com/explore` | `startUrls` |
| Album page | `https://www.erome.com/a/AlbumId1` | `videoUrls` or `startUrls` |

- Search filter: the site has no search filter, so `post` and `tag` are ignored and the plain search runs.
- A hashtag is the search `q=<tag>`. `tagSort` is ignored: the site's own order is used.
- The site has one video quality (720p), so every video is saved in it.
- `tags` come from the album page. `dates.posted` is the time of the earliest image of the album, and `null` for an album with only videos.
- An image has no `durationSeconds`: it is `null`.

### 🚀 How to scrape Erome videos and save the files

1. Open the actor on Apify and click **Try for free**.
2. Fill in a search, creators or album URLs, or paste erome.com URLs into `startUrls` or `videoUrls`.
3. Click **Start**.
4. Open the Output tab: **Files** links to your files in the Key-Value Store, **Saved files** lists the rows. Download the rows as JSON, CSV or Excel, or fetch them with the Apify API.

Example inputs:

```json
{ "videoUrls": ["https://www.erome.com/a/AlbumId1"] }
```

```json
{ "usernames": ["CreatorName"], "maxResults": 20, "createZip": true }
```

```json
{ "searchQueries": [{ "query": "example words", "filter": "all" }], "maxResults": 10, "extractDetails": true }
```

### 🔌 Run it your way

- **Schedule it** with Apify schedules.
- **Call it from the Apify API** and its clients (Python, JavaScript).
- **Connect it** to Make, n8n, Zapier, webhooks or Google Sheets.

### 💾 Where the files are

- On the Output tab, the **Files** link opens the run's default **Key-Value Store**. Each file is there under its name. `storedFile.url` is its public link.
- With `createZip` set to `true`, the store also holds `videos.zip` (key `videos.zip`) with all saved files, under the same names. The `OUTPUT` record has `zipUrl` (the link to the ZIP) and `fileCount` (files saved).
- A store that is not named is deleted by Apify after about 7 days. Download the files you need before that, or copy them to a named store.
- The storage is billed by Apify to your account, like any run.

`storedFile.status` says what happened to the file:

| Status | Meaning | Charged |
|---|---|---|
| `saved` | The file is in the store. | Yes, `video-file-saved`. |
| `skipped` | Not downloaded: the file is over `maxFileSizeMb`, the run reached `maxTotalDownloadMb`, the row has no file link, or the free plan limit of 50 files per run is reached. `storedFile.error` says which. | No |
| `failed` | The download failed. `storedFile.error` says why. | No |

The row of a skipped or failed file is still returned, free.

### ⚖️ Rights

Saved videos and images belong to their creators. You are responsible for having the right to save, keep and use them, and for following the law and erome.com terms.

### ⚙️ Input

| Input | Type | Default | Range | Meaning |
|---|---|---|---|---|
| `startUrls` | list of URLs | none | erome.com URLs | Search, profile or album URLs. The kind is found from the URL. |
| `searchQueries` | list | none | – | Items `{"query": "...", "filter": "all"}`. A plain text line means `{"query": text, "filter": "all"}`. The values `post` and `tag` of `filter` are ignored: the plain search runs. |
| `usernames` | list of text | none | – | Creator names, with or without `@`, or profile URLs. Every album of each creator. |
| `tags` | list of text | none | – | Tag names, or tag page URLs. A tag is searched as the plain search `q=<tag>`. |
| `tagSort` | text | empty | `latest`, `popular` | Ignored: the site's own order is used. |
| `videoUrls` | list of URLs | none | – | Album page URLs. One row per media file of the album. |
| `extractDetails` | yes/no | `false` | – | `false`: a short row, files first. `true`: the full row (views, likes, tags, links) plus `storedFile`. |
| `videoQuality` | text | `best` | `best` | The site has one video quality (720p), so `best` is the only value. |
| `maxFileSizeMb` | integer | `250` | 1 to 2,000 | A bigger file is skipped. |
| `maxTotalDownloadMb` | integer | `1024` | 1 to 20,000 | Files stop being saved when the saved files of the run together reach this size. |
| `createZip` | yes/no | `false` | – | Also save `videos.zip`. |
| `maxResults` | integer | `100` | 1 to 1,000 | Maximum files returned over all inputs. The free Apify plan returns up to 1,000 results per run. |
| `maxRequests` | integer | `200` | 1 to 1,000 | Maximum requests of the run (list pages and albums). |
| `maxPagesPerSource` | integer | `100` | 1 to 100 | Maximum list pages for one search, profile or tag. |
| `maxScrollsPerPage` | integer | `100` | 1 to 100 | Not used on this site (pages are numbered). |
| `maxRequestRetries` | integer | `2` | 0 to 5 | Retries after a network error or a server error. |
| `requestTimeoutSecs` | integer | `30` | 5 to 120 | Time limit of one request, in seconds. |
| `proxyConfiguration` | object | Apify proxy off | – | Proxy settings. |

Use at least one of `startUrls`, `searchQueries`, `usernames`, `tags` or `videoUrls`.

### 📦 Output: Erome video data

The short row (default) has `id`, `url`, `title`, `creator`, `durationSeconds`, `storedFile` and `dates`. With `extractDetails` set to `true`, it also has `views`, `likes`, `tags`, `thumbnailUrl`, `imageUrl` and the other full-row fields. A missing text, number or object is `null`. A missing list is `[]`.

| Field | Type | Meaning |
|---|---|---|
| `storedFile.key` | text or null | The store key of the saved file, e.g. `AlbumId1_MediaId1.mp4`. |
| `storedFile.url` | text or null | The public link to the saved file. |
| `storedFile.sizeBytes` | integer or null | The saved file's size in bytes. |
| `storedFile.mimeType` | text or null | The file's content type, e.g. `video/mp4` or `image/jpeg`. |
| `storedFile.quality` | text or null | The quality of the copy that was saved. |
| `storedFile.status` | text | `saved`, `skipped` or `failed`. |
| `storedFile.error` | text or null | Why the file was skipped or failed; `null` when saved. |

#### Example: a row

An example row (`startUrls` input with an album URL, `extractDetails` set to `true`).

```json
{
  "recordType": "video",
  "source": "erome",
  "id": "fmoFddfY",
  "url": "https://www.erome.com/a/qvCDjQbh",
  "mediaType": "image",
  "title": "Kymora",
  "creator": {
    "username": "itsMEboobie",
    "displayName": "itsMEboobie",
    "profileUrl": "https://www.erome.com/itsMEboobie"
  },
  "views": 10300,
  "likes": 47,
  "width": 1024,
  "height": 989,
  "tags": ["trans", "shemale", "ebony ts", "black ts"],
  "imageUrl": "https://s57.erome.com/9487/qvCDjQbh/fmoFddfY.jpg?v=1794291394",
  "storedFile": {
    "sizeBytes": 122459,
    "mimeType": "image/jpeg",
    "status": "saved"
  },
  "dates": {
    "posted": "2026-11-10T06:13:30Z",
    "scraped": "2026-11-14T05:49:10Z"
  }
}
```

### 📊 Run stats

Each run saves an `OUTPUT` record and a `RUN_HEALTH` record in the key-value store. `OUTPUT` has `fileCount` (files saved), `bytesSaved` (total size of the saved files), `zipUrl` (the link to `videos.zip`; `null` without a ZIP) and `stopReason` (the cap that ended the run, else `null`).

### 💰 Pricing

Pay per event, one event: **$8.00** per 1,000 saved files. There is no start fee. The row alone is free, and so are skipped and failed files.

| Event | Price | When it is charged |
|---|---|---|
| `video-file-saved` | $8.00 per 1,000 files | Each video or image file saved in your store. |

- Free plan: each run returns up to 1,000 results and saves up to 50 files. Paying plans have no cap per run.

### 🎯 Use cases

- Archive an Erome album or a creator's profile as named files, in one ZIP.
- Build a local library of videos from a keyword search, grouped by album.
- Feed an editing or content-review pipeline with `.mp4` files through the Apify API.
- Run the same pipeline over several video sites, since they share one output format.

### 🩺 If a run fails

The run health (the `RUN_HEALTH` record, `RUN_SUMMARY` and the last line of the log) names the cause, for example `site down: list request answered 500 x3`. Find that start of the message in the table.

| Error in the log / run health | What it means | What you do |
|---|---|---|
| `site down: <request> answered 500, 502-504, 520-526` | The site is offline or has a fault. The actor waits longer between tries, then stops the run. | Try again later. |
| `blocked: <request> answered 401, 403, 1020` or a captcha page | The site refused the request or showed a captcha page. | The actor already retries once through the Apify proxy. If it still fails, turn on the Apify proxy in the input (use the RESIDENTIAL group if it is already on). |
| `rate limited: <request> answered 429` | The site asks for fewer requests. The actor waits and slows down by itself. | Try again later. |
| `gone: <request> answered 404, 410` | The page or offer was removed. The actor skips it and it is not charged. | Nothing; this is normal. |
| `network error: <request> failed with timeout` (or connection error, DNS error) | A timeout or a broken connection. The actor retries with a pause. | Try again later. |
| `wrong answer: <request> returned HTML instead of JSON` (or an empty body) | The site answered with a page that is not data (HTML instead of JSON, an empty body). The site has probably changed. | Report it in the Issues tab; we fix it. |

### ❓ FAQ

#### How do I download all videos of one Erome creator?

Put the creator name in `usernames`, set `maxResults`, and turn on `createZip` to get one `videos.zip`.

#### How do I get the Erome video data and the files through the API?

Call the actor with the Apify API and read the rows of the run's dataset. Each row has `storedFile.url`, the link to its file in the run's Key-Value Store.

#### How much does it cost to bulk download Erome videos?

$8.00 per 1,000 saved files, nothing for the row alone, skipped or failed files. A free-plan run saves up to 50 files.

#### Can I use it with other video sites?

Yes. Our video actors share one output format, so the same pipeline reads them all. See the list below.

#### How do I export Erome videos to Excel or CSV?

Run the actor, open the Output tab and pick Excel or CSV in the export options. JSON, XML and HTML are there too, and the Apify API returns the same data.

### Data notice

This actor returns only what the site shows publicly at run time. We don't store or keep that data and are not its controller — you decide how you use it.

### 🔗 Other video scrapers (same schema)

#### Erome (this site)

- [Erome Video Scraper](https://apify.com/datawatcher/erome-scraper): links and data

#### Fikfap

- [Fikfap Video Scraper](https://apify.com/datawatcher/fikfap-scraper): links and data
- [Fikfap Video Downloader](https://apify.com/datawatcher/fikfap-video-downloader): saves the video files (.mp4)

#### RedGIFs

- [Redgifs Video Scraper](https://apify.com/datawatcher/redgifs-scraper): links and data
- [RedGIFs Video Downloader](https://apify.com/datawatcher/redgifs-video-downloader): saves the video files (.mp4)

#### Ultrathots

- [Ultrathots Video Scraper](https://apify.com/datawatcher/ultrathots-scraper): links and data
- [Ultrathots Video Downloader](https://apify.com/datawatcher/ultrathots-video-downloader): saves the video files (.mp4)

#### XFree

- [XFree Video Scraper](https://apify.com/datawatcher/xfree-scraper): links and data
- [XFree Video Downloader](https://apify.com/datawatcher/xfree-video-downloader): saves the video files (.mp4)

### 💬 Feedback and custom work

Need another portal, a field or a custom feed? Open an issue on the Issues tab.

# Changelog

This Actor's version history is a separate document: https://apify.com/datawatcher/erome-video-downloader/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Site URLs of any supported kind: search, account profile, tag or video page. The kind is found from the URL.

## `searchQueries` (type: `array`):

Searches, each {"query": "...", "filter": "all" | "post" | "tag"} (filter optional, default "all"). A plain text line is read as {"query": text, "filter": "all"}.

## `usernames` (type: `array`):

Account handles, with or without "@", or profile URLs. Every video of each account.

## `tags` (type: `array`):

Tag names exactly as the site writes them (case and prefixes kept, e.g. pl-Amatorzy), or tag page URLs.

## `tagSort` (type: `string`):

The order of tag pages. Empty - the site's default order.

## `videoUrls` (type: `array`):

Video page URLs. Each is read directly; one row per video.

## `maxResults` (type: `integer`):

Maximum number of videos returned, in total. Shared fairly over the inputs (each search, profile, tag or video URL gets its part; what one cannot fill goes to the others). Free plan Apify users get at most 1000 videos per run, whatever is set here (paying users have no cap).

## `maxRequests` (type: `integer`):

Maximum number of page requests the run makes, in total (listing pages and load-more steps; a direct video URL is one request).

## `maxPagesPerSource` (type: `integer`):

Maximum number of listing pages read for one search, profile or tag.

## `maxScrollsPerPage` (type: `integer`):

Maximum number of "Show more" / load-more steps on one listing page.

## `maxRequestRetries` (type: `integer`):

Retries of a request that failed on a network error or a server error. A block (403, 429, a challenge page) is never retried.

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

Time limit of one page request.

## `proxyConfiguration` (type: `object`):

Proxy settings, especially useful when many detail pages are requested.

## `extractDetails` (type: `boolean`):

false (default): a short row, files first (id, url, title, creator, duration, size, `storedFile`, dates). true: the full row of the links actor (views, likes, tags, tagged accounts, links ...) plus `storedFile`.

## `videoQuality` (type: `string`):

Which file to save. "best" is the full-quality .mp4 (`videoFileUrl`), "preview" the smaller copy (`previewVideoUrl`). erome.com has one video file per media (720p), so only "best" exists.

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

A video bigger than this is not saved (its `storedFile.status` is "skipped"); its row is still written.

## `maxTotalDownloadMb` (type: `integer`):

Stops saving files when the files of this run together reach this size (the rest are "skipped"); rows are still written.

## `createZip` (type: `boolean`):

Also put all saved files into one `videos.zip` in the Key-Value Store (needs disk space for the whole archive).

## Actor input object example

```json
{
  "startUrls": [
    "https://www.erome.com/search?q=maya+solar"
  ],
  "maxResults": 10,
  "maxRequests": 200,
  "maxPagesPerSource": 100,
  "maxScrollsPerPage": 100,
  "maxRequestRetries": 2,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "extractDetails": false,
  "videoQuality": "best",
  "maxFileSizeMb": 250,
  "maxTotalDownloadMb": 1024,
  "createZip": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per video (or, with Only video page URLs, one {videoUrl} row per video).

## `runSummary` (type: `string`):

OUTPUT: status, sources, pages and load-more steps, video pages read, unique videos, duplicates, media URLs found, challenges, requests used, early stop and its reason, source errors, account profiles, charged events.

## `runHealth` (type: `string`):

{status, reason}: ok, degraded, or failed.

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

The saved video files (.mp4) in the run's Key-Value Store. With "Create ZIP", `videos.zip` is among them and its public link is `zipUrl` in the OUTPUT record.

# 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 = {
    "startUrls": [
        "https://www.erome.com/search?q=maya+solar"
    ],
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("datawatcher/erome-video-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 = {
    "startUrls": ["https://www.erome.com/search?q=maya+solar"],
    "maxResults": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("datawatcher/erome-video-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 '{
  "startUrls": [
    "https://www.erome.com/search?q=maya+solar"
  ],
  "maxResults": 10
}' |
apify call datawatcher/erome-video-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datawatcher/erome-video-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/UdaHn7qTN2ISSteVo/builds/ZTymWKie0WI8v1Dmo/openapi.json
