# Tumblr Video Downloader (`automation-lab/tumblr-video-downloader`) Actor

Resolve direct video media URLs, captions, thumbnails, formats, dimensions, and provenance from supplied public Tumblr post URLs.

- **URL**: https://apify.com/automation-lab/tumblr-video-downloader.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Social media, Videos
- **Stats:** 2 total users, 1 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.35 / 1,000 item extracteds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Tumblr Video Downloader

Resolve directly downloadable native video URLs from supplied public Tumblr posts.

**Tumblr Video Downloader** turns public post permalinks into typed records with the direct media URL, post identity, blog, caption, thumbnail, format, dimensions, duration, and source provenance.
It is designed for recurring archival, creator asset retrieval, and downstream media-processing workflows.
No Tumblr login, cookies, or API key is required.

The Actor returns URLs and metadata in the default Apify dataset.
It does not copy large video binaries into Actor storage, so your workflow can decide when and where to download each asset.

### What does Tumblr Video Downloader do?

For every supplied public Tumblr post URL, the Actor:

1. validates that the URL is a supported Tumblr permalink;
2. normalizes blog-subdomain URLs to a canonical Tumblr post URL;
3. fetches the anonymous public post page;
4. finds native Tumblr video blocks in the post and public reblog trail;
5. extracts unique direct video media URLs;
6. adds post, blog, caption, thumbnail, format, and provenance fields;
7. writes one dataset record per resolved video.

The resulting `mediaUrl` can be sent to authorized storage, transcoding, transcription, cataloging, or backup systems.

### Who is this Tumblr video downloader for?

- **Creators** retrieving copies of their own public Tumblr video assets.
- **Archivists** preserving authorized public collections with source identity attached.
- **Media teams** feeding direct MP4 URLs into review, transcoding, or transcription tools.
- **Researchers** building reproducible datasets of selected public Tumblr video posts.
- **Automation developers** resolving batches of post URLs through the Apify API or schedules.
- **Social teams** keeping source post, blog, caption, and thumbnail context alongside each asset.

### Why use this Actor?

#### Direct media output

The primary result is the directly downloadable public media URL, not raw HTML or a browser screenshot.

#### Typed source provenance

Every row identifies the supplied URL, normalized permalink, post ID, blog, and whether the video came from the requested post body or its reblog trail.

#### Lightweight HTTP workflow

The Actor uses Tumblr's public server-rendered post data.
It does not launch a browser or enable an automatic paid proxy fallback.

#### Bounded batch processing

Process up to 50 unique public post URLs and stop after a configured number of video records.
Duplicate input permalinks are normalized and processed once.

### What data can I extract?

| Field | Type | Meaning |
| --- | --- | --- |
| `postId` | string | Stable Tumblr post identifier. |
| `postUrl` | URL | Public post permalink reported by Tumblr. |
| `sourceUrl` | URL | Exact supported Tumblr URL supplied in the input. |
| `canonicalPostUrl` | URL | Normalized `www.tumblr.com` URL used for retrieval. |
| `blogName` | string | Tumblr blog that owns the requested post. |
| `caption` | string, optional | Public summary or text caption when available. |
| `mediaUrl` | URL | Directly downloadable native Tumblr video URL. |
| `format` | string | Detected format, normally `mp4`. |
| `mimeType` | string, optional | Media MIME type reported by Tumblr. |
| `width` | integer, optional | Video width in pixels. |
| `height` | integer, optional | Video height in pixels. |
| `durationSeconds` | number, optional | Duration reported by Tumblr. |
| `thumbnailUrl` | URL, optional | Public poster or thumbnail image. |
| `provider` | string, optional | Video provider reported by the post block. |
| `videoIndex` | integer | One-based video position in this post's output. |
| `provenance` | string | `post` or `trail`. |
| `retrievedAt` | datetime | UTC retrieval timestamp. |

Optional fields are omitted when Tumblr does not publish them for a specific video.

### How to download a video from Tumblr

1. Open the Actor in Apify Console.
2. Add one or more public Tumblr post permalinks to **Tumblr post URLs**.
3. Set **Maximum videos** to the largest number of records you need.
4. Click **Start**.
5. Open the default dataset when the run finishes.
6. Copy or export each `mediaUrl` to your authorized download or processing system.

A working input is prefilled, so you can test the output before adding your own URLs.

### Input parameters

#### `startUrls`

Required array of 1–50 public HTTPS Tumblr post URLs.

Supported forms include:

```text
https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy
https://viralfrog.tumblr.com/post/818114486493921280
```

The Actor intentionally rejects arbitrary websites, HTTP URLs, tag feeds, search pages, dashboard URLs, and post URLs without a valid blog name and numeric post ID.

#### `maxItems`

Optional integer from 1 to 200.
The default is 20.
The Actor stops exporting after this many unique video records, even if more input posts remain.

#### Example input

```json
{
  "startUrls": [
    {
      "url": "https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy"
    },
    {
      "url": "https://viralfrog.tumblr.com/post/818114486493921280"
    }
  ],
  "maxItems": 2
}
```

### Example output

This representative row comes from the current public prefilled post:

```json
{
  "postId": "788607775569756160",
  "postUrl": "https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy",
  "sourceUrl": "https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy",
  "canonicalPostUrl": "https://www.tumblr.com/heartwarminganimals/788607775569756160",
  "blogName": "heartwarminganimals",
  "caption": "It wimdy",
  "mediaUrl": "https://va.media.tumblr.com/tumblr_sz511n6JJM1zug3u3.mp4",
  "format": "mp4",
  "mimeType": "video/mp4",
  "width": 854,
  "height": 484,
  "durationSeconds": 19,
  "thumbnailUrl": "https://64.media.tumblr.com/tumblr_sz511n6JJM1zug3u3_frame1.jpg",
  "provider": "tumblr",
  "videoIndex": 1,
  "provenance": "post",
  "retrievedAt": "2026-08-31T06:00:00.000Z"
}
```

Use the dataset's JSON, CSV, Excel, XML, RSS, or API export according to your downstream tool.

### How much does it cost to resolve Tumblr video URLs?

Pricing uses one one-time **Run started** event plus one **Item extracted** event for every useful Tumblr video dataset record.
Posts that fetch successfully but contain no supported native video do not incur an item event.
Failed and duplicate records are not item-charged.

Current item tiers decrease with account level:

| Tier | Price per Tumblr video |
| --- | ---: |
| Free | $0.0025944 |
| Bronze | $0.0022560 |
| Silver | $0.0017597 |
| Gold | $0.0013536 |
| Platinum | $0.0009024 |
| Diamond | $0.00063168 |

The one-time Run started event is $0.0125 per run.
At the Free tier, 1 resolved video costs about $0.0151, 10 videos cost about $0.0384, and 100 videos cost about $0.2719 including one Run started event.
Your Apify plan, run limits, and any downstream video transfer or storage costs are separate.

### Reliability, retries, and failure behavior

- Network failures, HTTP 429, and temporary Tumblr 5xx responses receive at most two bounded retries with backoff.
- Stable 4xx responses are not retried blindly.
- Invalid inputs fail the run with a non-zero status before any post is fetched.
- If one post fails, other valid posts can still produce results.
- The run fails if every requested Tumblr post fetch fails.
- A valid public post with no native downloadable video produces no row and no item event.
- External embeds are not misrepresented as native downloadable Tumblr files.

Use run logs to distinguish an invalid URL, deleted post, temporary upstream response, and a public post without a native video.

### Supported and unsupported content

Supported:

- anonymously reachable public Tumblr posts;
- Tumblr-hosted native video blocks;
- canonical `www.tumblr.com` and `*.tumblr.com/post/*` permalink forms;
- native videos found in the requested post body or public reblog trail.

Not supported:

- private, draft, login-only, or deleted posts;
- arbitrary custom-domain blog URLs;
- Tumblr search, tag, dashboard, or blog-feed discovery;
- DRM-protected or access-controlled media;
- guaranteed extraction from third-party players such as YouTube or Vimeo embeds;
- copying video binaries into the Actor's key-value store.

### Archive public Tumblr videos

A repeatable archival workflow can:

1. supply an approved list of public post URLs;
2. schedule the Actor daily or weekly;
3. export rows to a dataset or webhook;
4. deduplicate downstream by `postId` plus `mediaUrl`;
5. download authorized media to your chosen object store;
6. preserve `sourceUrl`, `blogName`, `caption`, and `retrievedAt` as provenance.

Tumblr can change, remove, or restrict media after retrieval.
Store the files and provenance you are authorized to preserve rather than treating a media URL as permanent storage.

### Media-processing integrations

#### Transcoding

Send `mediaUrl` to FFmpeg, a transcoding service, or a media pipeline after validating that your use is authorized.
Use `format`, `mimeType`, `width`, and `height` to choose a processing profile.

#### Transcription

Pass `mediaUrl` to a speech-to-text workflow and retain `postId` as the correlation key.

#### Spreadsheets and databases

Export the dataset to CSV or Excel, or connect Apify integrations to Google Sheets, Airtable, Make, Zapier, or your database.

#### Webhooks

Attach a run-succeeded webhook to notify a downstream worker when a batch is ready.
The worker can retrieve dataset rows using the run's default dataset ID.

### Run with the Apify API using cURL

Replace `APIFY_TOKEN` with your Apify token:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~tumblr-video-downloader/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "startUrls": [
      {"url": "https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy"}
    ],
    "maxItems": 1
  }'
```

Wait for completion, then use the returned run's `defaultDatasetId` to fetch items.

### Run with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/tumblr-video-downloader').call({
  startUrls: [
    { url: 'https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy' },
  ],
  maxItems: 1,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].mediaUrl);
```

### Run with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/tumblr-video-downloader').call(run_input={
    'startUrls': [
        {'url': 'https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy'},
    ],
    'maxItems': 1,
})

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item['mediaUrl'])
```

### Use Tumblr Video Downloader with MCP

Add the Apify MCP server to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/tumblr-video-downloader"
```

#### Claude Desktop setup

For Claude Desktop, add this remote server configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/tumblr-video-downloader"
    }
  }
}
```

#### Cursor setup

In Cursor, open **Settings → Tools & MCP → New MCP Server** and use the same Apify MCP URL shown above.

#### VS Code setup

In VS Code with MCP support enabled, add the same remote HTTP server URL to the workspace MCP configuration and authorize it with your Apify account.

Example prompts:

- “Resolve the native video URL and thumbnail from this public Tumblr post.”
- “Process these approved Tumblr permalinks and return post ID, blog, media URL, duration, and provenance.”
- “Prepare dataset rows for my authorized Tumblr video archive, stopping after 20 videos.”

### Responsible use and legality

Only process content that you are authorized to access and use.
Public availability does not remove copyright, privacy, publicity, contractual, or platform-policy obligations.
Respect creators' rights, Tumblr's terms, applicable law, takedown requests, and data-retention requirements.
Do not use the Actor to bypass login, privacy controls, access restrictions, DRM, or other technical protections.
You are responsible for deciding whether downloading, storing, transforming, or redistributing a specific video is permitted.

### Troubleshooting

#### Why did a public post produce zero rows?

The post may contain only images, text, audio, or a third-party embed rather than a native Tumblr video.
Check the run warning and verify that the anonymous public post visibly contains a Tumblr-hosted video.

#### Why was my URL rejected?

Use a public HTTPS post permalink with a Tumblr blog name and numeric post ID.
Search pages, tag pages, arbitrary custom domains, and non-Tumblr URLs are intentionally rejected.

#### Why is `durationSeconds` missing?

Tumblr does not publish duration in every public video block.
The direct media URL can still be valid when optional metadata is absent.

#### Why did the run fail after retries?

Tumblr may have returned a temporary 5xx/429 response, removed the post, or rejected anonymous access.
Review the exact status in the run log and retry later only for a genuinely transient response.

#### Does the Actor store the downloaded video?

No.
It exports the direct public media URL and metadata.
Your authorized downstream system controls binary download, transfer, retention, and storage cost.

### Related Actors

- [Tumblr Tagged Posts Scraper](https://apify.com/automation-lab/tumblr-tagged-posts-scraper) discovers and exports public posts from supported Tumblr tagged feeds.
- [Video to Text Transcriber](https://apify.com/automation-lab/video-to-text-transcriber) can turn an anonymously accessible direct video URL into timestamped text.
- [Public Webpage HTML Downloader](https://apify.com/automation-lab/public-webpage-html-downloader) stores raw or rendered HTML when your authorized workflow needs page snapshots rather than media records.

Use the tagged-post Actor for discovery, this Actor for selected post-to-video resolution, and downstream tools for authorized binary processing.

### FAQ

#### Can I process more than one video in a post?

Yes.
The Actor emits one row for every unique native video it finds, subject to `maxItems`.

#### Does it support reblogged videos?

Yes.
Public native video blocks in the reblog trail are emitted with `provenance: "trail"`.

#### Do I need a Tumblr account?

No.
The Actor supports only anonymously reachable public posts.

#### Does it use a proxy?

No automatic proxy or residential fallback is enabled.
The current implementation uses direct HTTP retrieval of public Tumblr pages.

#### Can I schedule recurring archives?

Yes.
Use Apify schedules and integrations, then deduplicate downstream with stable post and media identifiers.

#### Is the direct media URL permanent?

No guarantee is made.
Tumblr can change or remove public media URLs, so authorized archival workflows should retrieve required assets promptly and retain their provenance.

# Actor input Schema

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

Public Tumblr post permalinks. Supports www.tumblr.com/<blog>/<post-id> and <blog>.tumblr.com/post/<post-id> forms.

## `maxItems` (type: `integer`):

Stop after exporting this many unique direct video records across all supplied posts.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy"
    }
  ],
  "maxItems": 20
}
```

# Actor output Schema

## `overview` (type: `string`):

Open the default dataset overview containing one typed row per resolved native Tumblr video.

# 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": [
        {
            "url": "https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy"
        }
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/tumblr-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": [{ "url": "https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy" }],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/tumblr-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": [
    {
      "url": "https://www.tumblr.com/heartwarminganimals/788607775569756160/it-wimdy"
    }
  ],
  "maxItems": 20
}' |
apify call automation-lab/tumblr-video-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/tumblr-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/5wOJoh7sJS4H89KPe/builds/BigkxmiTq9fc4GnAk/openapi.json
