# Real-Debrid Stream URL Resolution

## The Problem

`POST /unrestrict/link` returns two URL fields that look similar but are **fundamentally different**:

| Field | Value | Playable? |
|-------|-------|-----------|
| `link` | `https://real-debrid.com/d/XXXXXX` | ❌ HTML download manager page |
| `download` | `https://laxN-N.download.real-debrid.com/d/XXXXXX/filename.mkv` | ✅ Direct CDN video URL |

The `link` field is the **original URL submitted** (per RD docs: "Original link"). The `download` field is the **generated unrestricted URL** (per RD docs: "Generated link"). These are almost always **different URLs** (`same=False` in the debug log).

## Root Cause

The bug was using `data.get("link")` instead of `data.get("download")`:

```python
# BUG — returned HTML download page:
stream_url_val = stream_url(data.get("link"))

# FIX — returns playable CDN URL:
stream_url_val = stream_url(data.get("download") or data.get("link"))
```

Torrentio confirms this in `TheBeastLT/torrentio-scraper` (`addon/moch/realdebrid.js`):
```javascript
return response.download;  // ← line 205, they use `download`, not `link`
```

## CDN URL Validation (proven)

Probed `https://lax4-4.download.real-debrid.com/d/WI32IQAZTVK3K117/The%20Matrix%20...mkv`:

```
curl -v -r 0-1048575 "https://lax4-4.download.real-debrid.com/d/..."
→ HTTP/1.1 206 Partial Content
```

- **No auth headers needed** — CDN URL works in browsers directly
- **Range requests supported** — HTTP 206 enables seeking
- **Content served as media** — not HTML
- The `/d/` in the CDN URL path is part of RD's CDN routing, NOT the same as `real-debrid.com/d/` which serves the HTML page

## `/streaming/transcode/{id}` (HLS) is NOT the primary approach

The transcode API `GET /streaming/transcode/{id}` (using `id` from `/unrestrict/link`) returned **HTTP 400 Bad Request** when tested with a real file (`rid=WI32IQAZTVK3K117 status=400`). Torrentio has the transcode path **commented out** — they prefer direct CDN URLs.

The transcode approach remains as a **fallback** for files where `response.streamable == 1` and CDN playback fails, but it is NOT reliable for all files.

## Implementation (in provider_resolvers.py)

### Primary: Direct CDN
```python
hls_url = await self._try_rd_streamable(unrestrict_data, headers)
if hls_url:
    stream_url_val = stream_url(hls_url)
else:
    stream_url_val = stream_url(unrestrict_data.get("download") or unrestrict_data.get("link"))
```

### Fallback: Transcode HLS
```python
async def _try_rd_streamable(self, unrestrict_data, headers):
    """Try GET /streaming/transcode/{id} → response.apple["1080p"]"""
    if not unrestrict_data.get("streamable"):
        return None
    rid = unrestrict_data.get("id")
    # ... calls RD API, returns HLS URL or None
```

## Debug Logging Pattern

The session added `download` field to the `rd_unrestrict_response` log, plus a `same` boolean:

```python
logger.info("rd_unrestrict_response",
    link=str(unrestrict_data.get("link", ""))[:100],
    download=str(unrestrict_data.get("download", ""))[:100],
    same=raw_link == raw_download,  # ← reveals if fields differ
    rid=unrestrict_data.get("id"),
    streamable=unrestrict_data.get("streamable"),
)
```

## Investigation Timeline (May 2026)

1. ❌ Suspected `/d/` URL needed redirect-following → HEAD returned HTML, no redirect
2. ❌ Built backend proxy to add Bearer token → proxy also received HTML
3. ❌ Concluded `/d/` URLs need browser cookies, not API tokens
4. ❌ Identified `/streaming/transcode/{id}` as alternative → returned 400
5. ✅ **Discovered `link` vs `download` field difference** → `download` is the CDN URL
6. ✅ Verified CDN URL serves 206 Partial Content with no auth needed
