# TurboGrab (`andrew_babo/turbograb`) Actor

- **URL**: https://apify.com/andrew\_babo/turbograb.md
- **Developed by:** [Andrew Babo](https://apify.com/andrew_babo) (community)
- **Stats:** 416 total users, 152 monthly users, 92.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## TurboGrab

High-speed, high-quality video acquisition for the Super Clipping pipeline.

TurboGrab resolves a page URL once, picks the best **h264** video-only format plus the best
audio-only format, then pulls both **in parallel** with many `&range=` chunk requests over the
same sticky exit IP, and stream-copy muxes a faststart mp4.

Measured on a 57-minute source (2026-09-04): 1 connection 17.9 MB/s, 16 parallel chunks
246.7 MB/s. Whole 1080p h264 video (283 MB) + audio (55 MB) + mux = **8.3 s**, versus 230 s for
the previous hosted 1080p route.

### Operations

| op | what it does |
|---|---|
| `resolve` | report the selected video/audio formats and their direct URLs, no download |
| `full` | parallel-range download + stream-copy mux into one faststart mp4 |
| `full_multi` | download only a byte range (`options.part={start,end}`) of the video — fan out N actors, each on its own exit, then concat client-side |
| `window` | same acquisition, then stream-copy cut every `options.segments[]` window |
| `capabilities` | ops/features/vcpus, needs no `source` |

### `full_multi` — multi-actor fan-out

Each call downloads only `options.part = { start, end }` bytes of the selected video format.
Set `options.audio = true` on one call to also fetch the full audio (55 MB, small enough for
one exit). The client opens N actors in parallel, each resolving its own signed URL (bound to
its own exit IP), downloads its byte range, and concatenates the parts with `ffmpeg concat`.

### Input

```json
{
  "op": "full",
  "source": "https://www.youtube.com/watch?v=VIDEO_ID",
  "options": {
    "min_height": 720,
    "max_height": 1080,
    "prefer_codec": "h264",
    "lanes": 16,
    "chunk_mb": 8,
    "proxy_ladder": ["direct", "DATACENTER", "RESIDENTIAL"],
    "allow_ytdlp_fallback": true
  }
}
```

For `op=window` add `options.segments: [{ "start_sec": 120, "end_sec": 165, "name": "clip_01" }]`.

### Output

One dataset row and a `RESULT` key-value record:

```json
{
  "ok": true,
  "op": "full",
  "artifacts": [{ "name": "source", "kv_key": "source.mp4", "url": "https://...", "bytes": 339300000 }],
  "meta": { "method": "ranged", "lane": "direct", "selected": { "video": { "height": 1080 } }, "probe": { "height": 1080 } },
  "timings": { "downloadMs": 6500, "muxMs": 1670, "totalMs": 8250 }
}
```

Failures never report success: `reason` is one of `QUALITY_TOO_LOW`, `UPSTREAM_BLOCKED`,
`TIMEOUT`, `OOM_LIMIT`, `BAD_INPUT`, `INTERNAL`.

### Notes

- The byte window goes in the URL (`&range=`), never as an HTTP `Range:` header — the header form
  hits Google's per-connection throttle.
- Resolve and every chunk share one proxy lane, because the signed media URL is IP-bound.
- `prefer_codec: "h264"` is the default on purpose: downstream render lanes stream-copy h264, so
  a vp9/av1 pick would trade seconds of download for minutes of transcode.
- If the ranged path fails, the actor falls back to a plain `yt-dlp` download and says so in
  `meta.method`; the real height is always verified with ffprobe before success.

# Actor input Schema

## `op` (type: `string`):

resolve = report the selected video/audio formats and their direct URLs, no download. full = parallel-range download of the selected video + audio and stream-copy mux into a faststart mp4. window = same acquisition, then cut one or many time windows (options.segments) with stream copy. capabilities = report ops/features/vcpus, needs no source.

## `source` (type: `string`):

YouTube (or other yt-dlp supported) PAGE url. Required for every op except capabilities.

## `options` (type: `object`):

min\_height (default 720), max\_height (default 1080), prefer\_codec (h264|any, default h264 so no transcode is needed), lanes (parallel chunk requests, default 8, max 64), chunk\_mb (default 4), segments \[{start\_sec,end\_sec,name}] for op=window, part {start,end} byte offsets for op=full\_multi, audio (bool, fetch full audio in same run) for op=full\_multi, format ("raw" default = hand over the source m4a untouched | "mp3" = transcode) for op=audio, player\_client (default "default,android"), extractor\_args (default "formats=missing\_pot"), cookies / cookies\_url, proxy (explicit proxy url), apify\_proxy {groups,country}, proxy\_ladder (default \["RESIDENTIAL","RESIDENTIAL","RESIDENTIAL"]), allow\_ytdlp\_fallback (default true).

## `output` (type: `object`):

{ signed\_upload\_url } to PUT a single artifact straight to your own storage.

## `cleanup` (type: `string`):

on\_success = keep only the result artifacts in the run's key-value store. always = also drop the artifact after it was pushed to signed\_upload\_url. off = keep everything for debugging.

## `callback` (type: `object`):

{ url, secret\_header: { name, value } } — POSTed with the result JSON when the run finishes.

## Actor input object example

```json
{
  "op": "full",
  "cleanup": "on_success"
}
```

# Actor output Schema

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

Full run result JSON: status, op, artifacts \[{name, kv\_key, url, bytes}], meta (selected formats, real probed height, lane, per-stream MB/s), timings, errors.

## `resultRecord` (type: `string`):

The same result JSON stored as the RESULT record of the default key-value store.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("andrew_babo/turbograb").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("andrew_babo/turbograb").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 '{}' |
apify call andrew_babo/turbograb --silent --output-dataset

```

## MCP server setup

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

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/ZbLCmUQ2D7rtRNp7C/builds/lABWrJ7lr693VYQII/openapi.json
