# Free Scraper — Embed-Based Streaming

A Stremio-compatible scraper that works **without a debrid subscription**. Resolves video hoster embeds (Filemoon, Voe, Streamtape, Rabbitstream, etc.) to direct m3u8/MP4 URLs, or serves embed iframes for the browser to handle Cloudflare.

Located at `/home/rurouni/Scraper Suite/free-scraper/`

## Architecture

```
TMDB Catalog → Movie ID → Embed Aggregator URLs → 
  ┌─ Primary: iframe embed (browser handles Cloudflare) ──▶ Play in iframe
  └─ Secondary: server-side extractor → m3u8 (if resolvable) ──▶ Direct play
```

**Critical insight**: Embed aggregator sites (Vidsrc, etc.) use Cloudflare protection that server-side Go/Node.js cannot bypass without a real browser engine. The PRIMARY playback path is **iframe embed** — the user's browser loads the embed page, passes Cloudflare, and plays the video. Server-side extractors (Filemoon, Voe, etc.) handle individual video hoster URLs that aren't behind Cloudflare.

### Embed Aggregators (iframe, browser handles Cloudflare)

Currently live (2026):
- `vidsrc.to/embed/movie/{tmdbId}` — ✅ Working
- `vidsrc.cc/embed/movie/{tmdbId}` — ✅ Working

Dead/blocked (do NOT use):
- `vidsrc.icu` — ENOTFOUND (domain dead)
- `vidsrc.net` — ENOTFOUND (domain dead)
- `rabbitstream.net` — DNS resolves but Cloudflare-blocked server-side

### Stremio Stream Response Format

For free streams, return `externalUrl` instead of `url` so Stremio opens an external player:

```json
{
  "streams": [
    {
      "name": "🎬 Free Stream",
      "description": "Embed player",
      "externalUrl": "https://vidsrc.to/embed/movie/27205",
      "behaviorHints": { "notWebReady": true, "isFree": true }
    }
  ]
}
```

`externalUrl` signals to Stremio that the stream needs to be opened in a browser/WebView rather than played inline. `notWebReady: true` prevents the Cast/Download button. `isFree: true` is a custom hint for client-side filtering.

### Test Dashboard

Located at `http://host:3092/test`. Features:
- Search movies via TMDB
- Shows clickable embed sources (Vidsrc.to, Vidsrc.cc)
- Click opens as iframe in-page — browser handles Cloudflare
- Also accepts direct embed URLs for manual testing

## Extractors (Portfolio of 6)

| Extractor | Domains | Complexity | Technique |
|-----------|---------|------------|-----------|
| **Filemoon** | filemoon.sx, filemoon.site, 8+ aliases | **High** | ECDSA secp256r1 keypair attestation → AES-256-GCM decrypt |
| **VidsrcNet** | vidsrc.net, vidsrc.me, vidsrc.icu | Medium | Companion JS redirect follow + iframe extraction |
| **Rabbitstream** | rabbitstream.net | Medium | JS obfuscation + AES-256-CBC decrypt from player script |
| **VidsrcTo** | vidsrc.to | Medium | RC4 token decoding + iframe extraction |
| **Streamtape** | streamtape.com/.net/.to | Low | Regex pattern matching (innerHTML, document.write) |
| **Voe** | voe.sx, voe-network.net | Low | Iframe follow + m3u8 regex |

## Implementation

Each extractor is a standalone async function in `src/extractors/`:
```js
export async function filemoonExtract(url, timeout) {
  // Returns { url: "https://...m3u8", headers: { Referer: "...", ... } }
}
```

Registry matches URL domains to extractors:
```js
import { resolveEmbed } from './extractors/registry.js';
const result = await resolveEmbed('https://filemoon.sx/e/abc123');
```

## Stremio Compatibility

- **Manifest**: `/manifest.json` — resources: stream, catalog
- **Stream**: `/stream/:type/:id.json` — returns embed iframe as primary, direct m3u8 as secondary
- **Catalog**: `/catalog/:type/:id.json` — TMDB-powered trending/search

## Tradeoffs vs Torrent + RD

| | Free (Embed) | Torrent + RD |
|---|---|---|
| Cost | Free | $3-4/mo |
| Quality | 720p-1080p | Up to 4K REMUX |
| Speed | Buffers occasionally | CDN, instant |
| Reliability | Sites change/block often | Stable |
| Complexity | High (crypto, JS obfuscation) | Medium (API calls) |

## Filemoon ECDSA Attestation Flow

Filemoon is the most sophisticated extractor. It performs a full cryptographic handshake:

1. **GET details** → `/api/videos/{id}/embed/details` → `embed_frame_url`
2. **POST challenge** → `/api/videos/access/challenge` → `{ challenge_id, nonce }`
3. **Generate ECDSA P-256 keypair** (Node.js crypto.generateKeyPairSync)
4. **Sign nonce** with SHA256withECDSA
5. **Convert DER signature** to raw (r + s, 32 bytes each)
6. **Build JWK** `{ crv: 'P-256', kty: 'EC', x, y }`
7. **Submit attestation** → `/api/videos/access/attest` → `{ token, viewer_id, confidence }`
8. **Request playback** → `/api/videos/{id}/embed/playback` → `{ iv, payload, key_parts[] }`
9. **AES-256-GCM decrypt** → key = key_parts[0] + key_parts[1], decrypt payload → `{ sources: [{ url }] }`

## When to Use Free Scraper

- Quick preview of a movie (no debrid setup needed)
- Testing/development environments
- Content not available on torrent trackers
- Backup when RD cache misses

## Running

```bash
cd /home/rurouni/Scraper\ Suite/free-scraper
npm install
node src/index.js
# Server on :3092
# Dashboard at http://localhost:3092/test
```

## Adding New Embed Domains

When an aggregator domain stops working (vidsrc.icu, vidsrc.net both went dead in 2026):
1. Search for current active embed aggregators via web search: "stremio free embed addon 2026"
2. Update the `altSources` array in `src/index.js`
3. Test via `/test` dashboard
