# xHamster Downloader (`maximedupre/xhamster-downloader`) Actor

Download public xHamster videos and photo galleries. Paste video URLs or IDs to get an MP4 download link, quality options, creator, tags, and view counts. Paste gallery URLs to get a link to every photo.

- **URL**: https://apify.com/maximedupre/xhamster-downloader.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Videos, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.00 / 1,000 videos

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

### 🎬 Save xHamster videos and photo galleries from a simple list of links

xHamster Downloader is for people who want to keep public xHamster videos and photos without copying links by hand. Paste video URLs, video IDs, or gallery URLs. For each video, you get an MP4 download link in the quality you pick, plus its title, creator, tags, and view counts. For each photo gallery, you get a direct link to every photo.

- Paste many links into the **[xHamster bulk video downloader](https://apify.com/maximedupre/xhamster-downloader/examples/xhamster-bulk-video-downloader)** to get every video in one run.
- Keep a clip for offline viewing with the **[xHamster MP4 downloader](https://apify.com/maximedupre/xhamster-downloader/examples/xhamster-mp4-downloader)**.
- Read the title, creator, tags, and counts of a clip with **[xHamster video info](https://apify.com/maximedupre/xhamster-downloader/examples/xhamster-video-info)**.
- Get a link to each image in a gallery with the **[xHamster photo downloader](https://apify.com/maximedupre/xhamster-downloader/examples/xhamster-photo-downloader)**.
- Start with one video ID in the **[xHamster downloader](https://apify.com/maximedupre/xhamster-downloader/examples/xhamster-downloader)** and get a working download link.

#### 📦 What you get for each video and gallery

**Videos**

- An MP4 download link in the quality you pick, and the quality you got.
- A list of all qualities and file formats that xHamster offers for the video.
- The video ID, page URL, title, and description.
- The creator name, ID, and profile URL.
- The length in seconds, width, height, orientation, and publish date.
- Tags, views, likes, dislikes, comments, and the thumbnail link.

**Photo galleries**

- The gallery ID, page URL, and title.
- A direct link to each photo in the gallery, with its width and height when known.

You do not need an xHamster account. The Actor works with public videos and galleries only.

#### 🚀 How to download xHamster videos and photos

1. Open the Actor and pick **Videos** or **Photo galleries** in **Result type**.
2. For videos, add video URLs or IDs in **Video URLs or IDs** and pick a **Video quality**.
3. For galleries, add gallery URLs in **Gallery URLs**.
4. Click **Start**. Each result shows up in the dataset as soon as it is ready.
5. Open the download links, or export the dataset as JSON, CSV, Excel, or another format.

Download links come from xHamster and work only for a limited time. Use them soon after the run.

#### ⚙️ Input

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `resultType` | string | Pick `videos` to get one result for each video, or `galleries` to get one result for each photo gallery. This field is required. The form fills in `videos` for you. The Actor only reads the field that matches the type you pick. |
| `videos` | array of strings | The public xHamster videos you want. Use a full video page URL, such as `https://xhamster.com/videos/some-title-xhAbC12`, or only the video ID, such as `xhAbC12`. Shorts, embed, mobile, and other language versions of video URLs work too. If you add the same video twice, you get it once. Values that are not a valid video URL or ID are skipped with a warning in the log. The form fills in `xhdGDXX` as a starter example. |
| `quality` | string | The quality of the download link: `best`, `720p`, `480p`, `240p`, or `144p`. The default is `best`, which gives the highest MP4 quality xHamster offers, at most 720p. When a video does not have the quality you pick, you get the best quality below it. If there is no lower quality, you get the lowest quality it offers. |
| `galleryUrls` | array | The public xHamster photo gallery URLs you want, such as `https://xhamster.com/photos/gallery/some-title-12345678`. Each gallery gives one result with links to its photos. Repeated galleries are saved once. |

**Example input**

```json
{
  "resultType": "videos",
  "quality": "best",
  "videos": [
    "xhdGDXX"
  ]
}
```

#### 🧾 Output

**Output fields**

Each row is either a video or a photo gallery. The `type` field tells you which one it is.

**Video row**

| Field | Type | What it does |
| --- | --- | --- |
| `type` | string | Always `video` for a video row. |
| `videoId` | string | The xHamster ID of the video. |
| `url` | string | The main xHamster page URL of the video. |
| `title` | string | The title of the video. |
| `description` | string or null | The description of the video, if it has one. |
| `downloadUrl` | string | A link to download the video file in the quality shown in `quality`. |
| `quality` | string | The quality of the download link, such as `720p`. |
| `formats` | array of objects | All qualities and file formats that xHamster offers for the video. |
| `formats.quality` | string | One video quality, such as `720p`. |
| `formats.format` | string | The file format of that quality, such as `mp4` or `hls`. |
| `creator` | object or null | The person or channel that posted the video. |
| `creator.id` | string or null | The xHamster ID of the creator. |
| `creator.name` | string or null | The name of the creator. |
| `creator.url` | string or null | The xHamster profile page of the creator. |
| `durationSeconds` | integer or null | How long the video is, in seconds. |
| `width` | integer or null | The width of the video in pixels. |
| `height` | integer or null | The height of the video in pixels. |
| `orientation` | string or null | The video orientation that xHamster states for the video. |
| `publishedAt` | string or null | When the video was published, as an ISO 8601 date and time. |
| `tags` | array of strings | The tags of the video. |
| `viewCount` | integer or null | How many times the video was viewed. |
| `likeCount` | integer or null | How many likes the video has. |
| `dislikeCount` | integer or null | How many dislikes the video has. |
| `commentCount` | integer or null | How many comments the video has. |
| `thumbnailUrl` | string or null | A link to the thumbnail image of the video. |

**Example video row**

```json
{
  "type": "video",
  "videoId": "xhdGDXX",
  "url": "https://xhamster.com/videos/47-year-old-busty-milf-moon-flower-gets-ass-fucked-and-does-xhdGDXX",
  "title": "47-year-old busty MILF Moon Flower gets ass-fucked and does",
  "description": "Now that she's sucked dick and taken a load all over her big, beautiful tits, 47-year-old MILF Moon Flower is back to show us how much she enjoys cocks in her pink pussy and tight ass, too, and while she does it, she engages in some ass-to-mouth action. Once again, the guy finishes off by paying tribute to her breasts.  Hobbies: Swimming, bicycling and fitness.",
  "downloadUrl": "https://video7.xhcdn.com/key=3p4m8OS2mCdV-TqENe+QrQ,end=1793066400,limit=3/data=192.227.205.70-dvp/speed=0/026/974/000/720p.h264.mp4",
  "quality": "720p",
  "formats": [
    {
      "quality": "144p",
      "format": "mp4"
    },
    {
      "quality": "240p",
      "format": "mp4"
    },
    {
      "quality": "480p",
      "format": "mp4"
    },
    {
      "quality": "720p",
      "format": "mp4"
    },
    {
      "quality": "144p",
      "format": "hls"
    },
    {
      "quality": "240p",
      "format": "hls"
    },
    {
      "quality": "480p",
      "format": "hls"
    },
    {
      "quality": "720p",
      "format": "hls"
    }
  ],
  "creator": {
    "id": "127864703",
    "name": "Scorepass",
    "url": "https://xhamster.com/users/scorepass"
  },
  "durationSeconds": 623,
  "width": 1366,
  "height": 720,
  "orientation": "straight",
  "publishedAt": "2025-11-09T00:01:40.000Z",
  "tags": [
    "MILF Bundle",
    "Moon Flower",
    "Steve Hardy",
    "Anal",
    "Big Tits",
    "Blonde",
    "Brunette",
    "Cum on Tits",
    "HD Videos",
    "Hardcore",
    "MILF",
    "Mature",
    "Nude",
    "Titty Fucking",
    "Fucked",
    "Mature Women",
    "Matures",
    "Busty",
    "Cuty",
    "Guy",
    "Melone",
    "Paid",
    "Old MILF",
    "Breasts",
    "Load",
    "Blonde Girl",
    "Giant Boob",
    "Cumshot on Tits",
    "Finish",
    "Swimming",
    "Older MILF",
    "Brunette Girl",
    "Tight Asses",
    "Beautiful",
    "Hardcore Mature",
    "How Much",
    "Huge Tit Mature",
    "Big Tit Mature",
    "Mooning",
    "Ilikecomix"
  ],
  "viewCount": 11290119,
  "likeCount": 29519,
  "dislikeCount": 434,
  "commentCount": 79,
  "thumbnailUrl": "https://ic-vt-nss.xhcdn.com/a/NmI3NzQ0NDM1OGM3NzJhN2U4MzZkN2VkOTRmNmZmMjM/s(w:1280,h:720),webp/026/974/000/v2/2560x1440.226.webp"
}
```

**Photo gallery row**

| Field | Type | What it does |
| --- | --- | --- |
| `type` | string | Always `gallery` for a photo gallery row. |
| `galleryId` | string | The xHamster ID of the photo gallery. |
| `url` | string | The main xHamster page URL of the gallery. |
| `title` | string | The title of the gallery. |
| `photos` | array of objects | The photos in the gallery. |
| `photos.imageUrl` | string | A link to download the photo. |
| `photos.width` | integer or null | The width of the photo in pixels. |
| `photos.height` | integer or null | The height of the photo in pixels. |

**Example photo gallery row**

```json
{
  "type": "gallery",
  "galleryId": "16613137",
  "url": "https://xhamster.com/photos/gallery/beach-16613137",
  "title": "Beach",
  "photos": [
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/NTdlYjQwOTM1MWQ4ZTIxMjVlZDNiYzQ3OGIwYzZiNDI/webp/000/520/312/312_1000.jpg",
      "width": 2000,
      "height": 924
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/Yjk1M2ZjMjEwMjc0M2U4YTNlZGFhMTUzOTc0NzRmZDI/webp/000/520/312/298_1000.jpg",
      "width": 2000,
      "height": 1500
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/ZmM3ZGYyZWQ5MDg5Nzg1OGZmZmJiNjVhNjIxODZiY2Y/webp/000/520/312/299_1000.jpg",
      "width": 1200,
      "height": 1600
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/YjEyYzM0ZTc1NTE5NmQ5ZmNjMTk2Mzc4OGNhM2U5ZjA/webp/000/520/312/300_1000.jpg",
      "width": 1599,
      "height": 1200
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/MzgyNWVjN2VkNDRhNjM2MDFhYmYxOThlMDkzYmUxNTE/webp/000/520/312/304_1000.jpg",
      "width": 901,
      "height": 2000
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/MmFiNTA2OWRjODBhMWI0YzE3MDMzMDA5N2UxMDY0YjY/webp/000/520/312/305_1000.jpg",
      "width": 2000,
      "height": 924
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/MWVhMmFhNDllYTgwNDMzNmZjNjI2M2ZlMTc2YmY3MGE/webp/000/520/312/310_1000.jpg",
      "width": 924,
      "height": 2000
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/ZmIxOWUyOWYzOWM0ZmZhMjhlZWQxMDFhZTc4NGIxNTA/webp/000/520/312/301_1000.jpg",
      "width": 1125,
      "height": 2000
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/YzBlZTNiZDY2ZWMyM2NjOTUzNDc1MjFjMDNiMWQxNTU/webp/000/520/312/302_1000.jpg",
      "width": 901,
      "height": 2000
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/Yzk3NTFlMzUzOTBhZjI3Mjk2YWRmZjY3MTUxNDE5YWU/webp/000/520/312/303_1000.jpg",
      "width": 901,
      "height": 2000
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/NjNjN2RmMmFlZmViMTg1NzcxZmQ0YjZjZTRhY2I5NDk/webp/000/520/312/292_1000.jpg",
      "width": 848,
      "height": 1131
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/ZTg0Yzg0YzdlMmU0OTQ4YjNiZjM1ODg2MTAxNzk3MTk/webp/000/520/312/293_1000.jpg",
      "width": 848,
      "height": 1131
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/MGI4MjcyOWVkYjdkMDMwMzdmMzU2ZTNjMDBhMjU1YzI/webp/000/520/312/294_1000.jpg",
      "width": 640,
      "height": 480
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/NWQ5OGRhODU2MGVkMDAzNTIzYTM4Y2UxMjM0MTNmZmE/webp/000/520/312/295_1000.jpg",
      "width": 480,
      "height": 640
    },
    {
      "imageUrl": "https://ic-ph-nss.xhcdn.com/a/MTlkNmZmZmMzMzliNzVmOWZiYThhNjVhZjk0YjEzZTI/webp/000/520/312/296_1000.jpg",
      "width": 480,
      "height": 640
    }
  ]
}
```

#### 💳 Pricing

This Actor uses pay-per-event pricing. You pay only for what is saved to your dataset:

- **Video:** $0.009 for each video saved with its download link and details.
- **Photo gallery:** $0.005 for each photo gallery saved with links to its photos.

You are not charged for links that are not valid, videos or galleries that cannot be found, items that cannot be read, or repeated links. If you set a maximum cost for the run, the Actor stops when it reaches that limit.

#### 🔌 Integrations

You can connect xHamster Downloader to other apps and services with Apify integrations, such as Make, Zapier, Google Drive, webhooks, and the Apify API. For example, you can send each new download link to a sheet or start a run from your own code.

https://www.youtube.com/watch?v=bNACk1_S_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Is it safe and legal to use an xHamster video downloader?

The Actor only reads public pages that anyone can open without an account. It does not sign in, and it does not get private or paid videos. Download only content you own or have permission to save, and follow the xHamster terms and the laws where you live.

##### Can I get 1080p or 4K videos?

The MP4 download link is at most 720p. When xHamster offers higher qualities, they show in the `formats` list only as HLS streams.

##### What happens if a video does not have the quality I picked?

You get the best quality below it. If there is no lower quality, you get the lowest quality the video has. The `quality` field shows the quality you got.

##### Does the Actor save the video file itself?

No. Each row gives a download link that you can open to save the file. The link works only for a limited time, so use it soon after the run.

##### Can I mix videos and photo galleries in one run?

No. Each run reads one type: the type you pick in **Result type**. Start a second run for the other type.

##### What if a link is wrong or a video was removed?

The Actor writes a warning in the log, skips that link, and moves on to the next one. You are not charged for it.

##### Do I need an xHamster account?

No. The Actor works with public videos and photo galleries without any login.

### 📝 Changelog

**v0.0** (26-10-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~xhamster-downloader/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [XHamsterLive Downloader](https://apify.com/maximedupre/xhamsterlive-downloader): get media links and details from XHamsterLive rooms, model pages, and saved videos.
- [Pornhub Video Downloader](https://apify.com/maximedupre/pornhub-downloader): get Pornhub video details and download links from video URLs, listing URLs, or search terms.
- [XVideos Video Downloader](https://apify.com/maximedupre/xvideos-downloader): turn XVideos watch-page URLs into MP4 and HLS links with titles and uploaders.
- [XNXX Video Downloader](https://apify.com/maximedupre/xnxx-video-downloader): turn XNXX video URLs or IDs into media links with titles, durations, and thumbnails.
- [SpankBang Video Downloader](https://apify.com/maximedupre/spankbang-downloader): get MP4 or HLS links, quality, tags, and views from SpankBang watch URLs.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `resultType` (type: `string`):

Videos gives one result for each video. Photo galleries gives one result for each gallery.

## `videos` (type: `array`):

Add the public xHamster videos you want. Use a full video page URL, such as https://xhamster.com/videos/some-title-xhAbC12, or only the video ID, such as xhAbC12. Shorts, embed, mobile and other language versions of xHamster video URLs work too. If you add the same video twice, you get it once.

## `quality` (type: `string`):

The video quality you want for the download link. "Best available" gives the highest quality that xHamster offers as an MP4 file. This is at most 720p. When xHamster does not offer the quality you pick for a video, you get the best quality below it. If there is no lower quality, you get the lowest quality it offers. Each result lists all the qualities that xHamster offers for that video. Higher qualities, such as 1080p, show there only as HLS streams.

## `galleryUrls` (type: `array`):

Add the public xHamster photo gallery URLs you want, such as https://xhamster.com/photos/gallery/some-title-12345678. Each gallery gives one result with links to its photos.

## Actor input object example

```json
{
  "resultType": "videos",
  "videos": [
    "xhdGDXX"
  ],
  "quality": "best"
}
```

# Actor output Schema

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

The videos or photo galleries from this run.

# 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 = {
    "resultType": "videos",
    "videos": [
        "xhdGDXX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/xhamster-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 = {
    "resultType": "videos",
    "videos": ["xhdGDXX"],
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/xhamster-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 '{
  "resultType": "videos",
  "videos": [
    "xhdGDXX"
  ]
}' |
apify call maximedupre/xhamster-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/xhamster-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/Bo5rvrounx2D3LPtG/builds/8SPaVgwu9TwVRgFaa/openapi.json
