pstreams-providers/.docs/content/3.in-depth/5.flags.md
2026-01-27 12:52:05 -07:00

177 lines
6.4 KiB
Markdown

# Flags
Flags are the primary way the library separates entities between different environments and indicates special properties of streams.
For example, some sources only give back content that has the CORS headers set to allow anyone, so that source gets the flag `CORS_ALLOWED`. Now if you set your target to `BROWSER`, sources without that flag won't even get listed.
Sometimes a source will block netlify or cloudflare. Making self hosted proxies on P-Stream impossible. In cases where it would break some user's experiences, we should require the extension.
## Available Flags
- **`CORS_ALLOWED`**: Headers from the output streams are set to allow any origin.
- **`IP_LOCKED`**: The streams are locked by IP: requester and watcher must be the same.
- **`CF_BLOCKED`**: *(Cosmetic)* Indicates the source/embed blocks Cloudflare IPs. For actual enforcement, remove `CORS_ALLOWED` or add `IP_LOCKED`.
- **`PROXY_BLOCKED`**: *(Cosmetic)* Indicates streams shouldn't be proxied. For actual enforcement, remove `CORS_ALLOWED` or add `IP_LOCKED`.
- **`MKV_REQUIRED`**: The stream is MKV format and requires a player that supports it. Most browsers cannot play MKV; use this flag so browser targets filter these out. Native and desktop/mobile apps with proper players receive these streams when using the `native` target.
## How Flags Affect Target Compatibility
### Stream-Level Flags Impact
**With `CORS_ALLOWED`:**
- ✅ Browser targets (can fetch and play streams)
- ✅ Extension targets (bypass needed restrictions)
- ✅ Native targets (direct stream access)
**Without `CORS_ALLOWED`:**
- ❌ Browser targets (CORS restrictions block access)
- ✅ Extension targets (can bypass CORS)
- ✅ Native targets (no CORS restrictions)
**With `IP_LOCKED`:**
- ❌ Proxy setups (different IP between request and playback)
- ✅ Direct connections (same IP for request and playback)
- ✅ Extension targets (when user has consistent IP)
**With `CF_BLOCKED` *(cosmetic only)*:**
- 🏷️ Informational label indicating Cloudflare issues
- ⚠️ **Still requires removing `CORS_ALLOWED` or adding `IP_LOCKED` for actual enforcement**
**With `PROXY_BLOCKED` *(cosmetic only)*:**
- 🏷️ Informational label indicating proxy incompatibility
- ⚠️ **Still requires removing `CORS_ALLOWED` or adding `IP_LOCKED` for actual enforcement**
**With `MKV_REQUIRED`:**
- ❌ Browser targets (most browsers cannot play MKV)
- ✅ Extension targets (depends on player)
- ✅ Native targets (desktop/mobile apps with proper players can play MKV)
### Provider-Level Flags Impact
**With `CORS_ALLOWED`:**
- Source appears for all target types
- Individual streams still need appropriate flags
**Without `CORS_ALLOWED`:**
- Source only appears for extension/native targets
- Hidden entirely from browser-only users
### Important: Cosmetic vs Enforcement Flags
**Cosmetic flags** (`CF_BLOCKED`, `PROXY_BLOCKED`) are informational labels only. They don't enforce any behavior.
**Enforcement flags** (`CORS_ALLOWED`, `IP_LOCKED`) actually control stream compatibility:
- **Remove all flags**: Most common way to make streams extension/native-only (no browser support)
- **Add `IP_LOCKED`**: Prevents proxy usage when `consistentIpForRequests` is false (rarely needed - most extension-only streams just use no flags)
### The Golden Rule
**Extension-only providers:** Remove all flags (most common case) when streams only work with extensions (e.g., need special headers or IP restrictions that only extensions can bypass).
**Universal providers:** Include `CORS_ALLOWED` flags when using M3U8 proxies or streams that can work across all targets.
## Comprehensive Flags Guide
For detailed information about using flags in your scrapers, including:
- When and how to use each flag
- Provider-level vs stream-level flags
- Best practices and examples
- How flags affect stream playback
See the [Flags System section](/in-depth/advanced-concepts#flags-system) in Advanced Concepts.
## Quick Reference
```typescript
import { flags } from '@/entrypoint/utils/targets';
import { createM3U8ProxyUrl } from '@/utils/proxy';
// Extension-only streams (MOST COMMON - just remove all flags)
return {
stream: [{
id: 'primary',
type: 'hls',
playlist: createM3U8ProxyUrl(originalUrl, ctx.features, headers),
headers,
flags: [], // No flags = extension/native only, but this case doesn't make sense because the stream is getting proxied.
captions: []
}]
};
// Universal streams with CORS support
return {
stream: [{
id: 'primary',
type: 'hls',
playlist: createM3U8ProxyUrl(originalUrl, ctx.features, headers),
headers, // again listing headers twice so the extension can use them.
flags: [flags.CORS_ALLOWED], // Works across all targets
captions: []
}]
};
// Direct streams (no proxy needed)
return {
stream: [{
id: 'primary',
type: 'hls',
playlist: 'https://example.com/playlist.m3u8',
flags: [flags.CORS_ALLOWED], // Stream can be played directly in browsers
captions: []
}]
};
// Extension-only streams (usual approach - just remove all flags)
return {
stream: [{
id: 'primary',
type: 'hls',
playlist: 'https://example.com/playlist.m3u8',
flags: [], // No flags = extension/native only (most common)
captions: []
}]
};
// Cloudflare-blocked streams with cosmetic label (if needed)
return {
stream: [{
id: 'primary',
type: 'hls',
playlist: 'https://example.com/playlist.m3u8',
flags: [flags.CF_BLOCKED], // Cosmetic only - still extension/native only due to no CORS_ALLOWED
captions: []
}]
};
// IP-locked streams (when you specifically need consistent IP)
return {
stream: [{
id: 'primary',
type: 'hls',
playlist: 'https://example.com/playlist.m3u8',
flags: [flags.IP_LOCKED], // Prevents proxy usage when IP consistency required
captions: []
}]
};
// MKV streams (native/desktop/mobile apps with proper players only; filtered out for browser)
return {
stream: [{
id: 'primary',
type: 'file',
qualities: { 1080: { type: 'mp4', url: 'https://example.com/video.mkv' } },
flags: [flags.MKV_REQUIRED], // Browser disallows; native target enables these sources
captions: []
}]
};
// Provider-level flags affect source visibility
export const myScraper = makeSourcerer({
id: 'my-scraper',
name: 'My Scraper',
rank: 150,
flags: [flags.CORS_ALLOWED], // Source shows for all targets
scrapeMovie: comboScraper,
scrapeShow: comboScraper,
});
```