PornHub API
A fully asynchronous Python API wrapper and scraper for Pornhub. Fetch videos, GIFs, shorts, albums, playlists, pornstars, models, channels, and user profiles — with full account login support. Powered by the eaf_base_api networking engine.
Other Options:
• PayPal
• Ko-Fi
For extended features, enterprise integrations, or custom commercial licensing, please contact EchterAlsFakeBS@proton.me.
Installation
Install from PyPI using pip:
pip install unofficial-api-for-pornhub
For TS→MP4 remuxing support (recommended for HLS downloads), install with the optional av dependency:
pip install unofficial-api-for-pornhub[av]
eaf_base_api ≥ 4.0.0 is installed automatically as a dependency.
Quick Start
Every method in this API is asynchronous. You need to run your code inside an async function:
import asyncio
from pornhub_api import Client
async def main():
client = Client()
# Fetch a video
video = await client.get_video("https://www.pornhub.com/view_video.php?viewkey=...")
# Access metadata
print(video.title)
print(video.views)
print(video.tags)
# Download the video
from base_api import DownloadConfigHLS
config = DownloadConfigHLS(quality="best", path="./downloads")
await video.download(configuration=config)
asyncio.run(main())
Configuration
The API uses eaf_base_api ≥ 4.0.0 for networking. Configure its singular proxy, bounded request attempts, timeouts, and other runtime behavior through a custom BaseCore.
Please refer to the eaf_base_api Documentation for the complete reference on how to set up RuntimeConfig and properly integrate it with this API.
from base_api import BaseCore
from base_api.modules.config import RuntimeConfig
from pornhub_api import Client
my_config = RuntimeConfig()
my_config.proxy = "socks5://127.0.0.1:9050"
my_config.request_attempts = 3
core = BaseCore(configuration=my_config)
client = Client(core=core)
Client
The Client class is your entry point for all interactions. It manages the session, headers, cookies, and authentication — providing methods to fetch individual resources, search, and access account features.
from pornhub_api import Client
from base_api import BaseCore
# Basic initialization
client = Client()
# With custom core and login credentials
client = Client(
core=BaseCore(),
email="user@example.com",
password="password",
login=False,
)
# Run inside an async function so login can be awaited.
await client.login()
Constructor Parameters
- core BaseCore — Networking core instance. The source default is one module-created
BaseCore()shared by callers that omit this argument; pass an explicit core for independent configuration and lifecycle. - email str | None — Account email for login
- password str | None — Account password for login
- login bool — If
True, schedules login withasyncio.create_task()and therefore requires a running event loop. Preferlogin=Falsefollowed byawait client.login()when completion must be observed.
Methods
Fetch Video get_video()
Video object. By default, loads metadata via the Webmaster API; set load_html=True for full HTML-scraped data including categories, tags, and author information.Parameters
- url str — The full Pornhub video URL
- load_html bool — If
True, fetches and parses the full HTML page for extended metadata (categories, tags, author info, m3u8 URLs) - load_api bool — If
True(default), fetches metadata via the Webmaster API for faster loading
Returns
→ VideoFetch Pornstar get_pornstar()
Pornstar object with bio, about, and info fields.Parameters
- url str — The full Pornhub pornstar profile URL
- load_html bool — If
True(default), parses the HTML profile page for metadata
Returns
→ PornstarFetch Model get_model()
Model object.Parameters
- url str — The full Pornhub model profile URL
- load_html bool — If
True(default), parses the HTML profile page
Returns
→ ModelFetch User get_user()
User object.Parameters
- url str — The full Pornhub user profile URL
- load_html bool — If
True(default), parses the HTML profile page
Returns
→ UserFetch Channel get_channel()
Channel object with name, stats, and metadata.Parameters
- url str — The full Pornhub channel URL
- load_html bool — If
True(default), parses the HTML page
Returns
→ ChannelFetch Playlist get_playlist()
Playlist object with title, description, tags, and video counts.Parameters
- url str — The full Pornhub playlist URL
- load_html bool — If
True(default), parses the HTML page for metadata
Returns
→ PlaylistFetch Album get_album()
Album object with rating, views, tags, and author information.Parameters
- url str — The full Pornhub album URL
- load_html bool — If
True(default), parses the HTML page
Returns
→ AlbumFetch GIF get_gif()
GIF object with title, votes, views, tags, and direct download URL.Parameters
- url str — The full Pornhub GIF URL
- load_html bool — If
True(default), parses the HTML page
Returns
→ GIFFetch Short get_short()
Short object with title, likes, and streaming URLs.Parameters
- url str — The full Pornhub short URL
- load_html bool — If
True(default), parses the HTML page
Returns
→ ShortSearch Videos search_videos()
Parameters
- query str — Search keywords
- production_type str | None — Filter by
"professional"or"homemade" - sort_by str | None —
"mr"(Most Recent),"mv"(Most Viewed),"tr"(Top Rated) - duration_min str | None — Minimum duration in minutes:
"10","20", or"30" - duration_max str | None — Maximum duration in minutes:
"10","20", or"30" - pages int — Number of result pages to iterate (default:
5) - iterator_config IteratorConfig | None — Optional v4 concurrency, ordering, eager-source, retry, and error-handling policy. By default, no media source is loaded eagerly.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Search GIFs search_gifs()
Parameters
- query str — Search keywords
- category str | None — Category filter:
"gay"or"transgender"(default: straight) - search_filter str | None —
"mr"(Most Recent),"mv"(Most Viewed),"tr"(Top Rated) - pages int — Number of result pages (default:
5) - iterator_config IteratorConfig | None — Optional v4 iterator policy. By default, no media source is loaded eagerly.
Returns
→ AsyncGenerator[ScrapeResult[GIF], None]Search HubTraffic API search_hubtraffic()
Parameters
- query str — Search keywords
- category str | None — Category filter string
- sort_by str | None —
"newest","mostviewed", or"rating" - period str | None — Time period:
"weekly","monthly", or"alltime" - pages int — Number of result pages (default:
5) - iterator_config IteratorConfig | None — Optional v4 iterator policy. The default uses higher page/item concurrency for HubTraffic but still performs no eager media-source load.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Login login()
client.account with user data and enables access to account-specific methods (recommended, history, favorites, feed, subscriptions).Parameters
- force bool — If
True, re-login even if already logged in - throw bool — If
True(default), raisesLoginFailedon failure; ifFalse, returnsFalseinstead
Returns
→ boolRaises
- LoginFailed — If credentials are invalid or login request fails
- ClientAlreadyLogged — If already logged in and
force=False
Video
dataclass Inherits from BaseMedia. Represents a single video with metadata from both HTML scraping and the Webmaster API. Supports dual loading modes: API-only (fast) and HTML (full data including m3u8 URLs for downloading).
Attributes
| Attribute | Type | Source | Description |
|---|---|---|---|
url | str | — | The video page URL |
video_id | str | None | — | Extracted viewkey from URL |
title | str | None | API / HTML | Video title |
duration | int | None | API / HTML | Video duration in seconds |
thumbnail | str | None | API / HTML | Preview thumbnail URL |
views | str | None | API / HTML | View count |
likes | str | None | API / HTML | Like / rating count |
publish_date | str | None | API / HTML | Upload / publish date |
categories | list[str] | None | API / HTML | Category names |
tags | list[str] | None | API / HTML | Tag names |
rating_percent | str | float | None | API | Webmaster API rating percentage |
is_hd | bool | None | HTML | Whether the video is HD |
is_vr | bool | None | HTML | Whether the video is VR |
is_vertical | bool | None | HTML | Whether the video is vertical (portrait) |
is_video_unavailable | bool | None | HTML | Whether the video is unavailable |
is_video_unavailable_in_your_country | bool | None | HTML | Whether the video is geo-blocked |
available_qualities | list[int] | None | HTML | Sorted list of available resolution heights |
m3u8_base_url | str | None | HTML | Synthesized master m3u8 playlist for HLS download |
author_thumbnail | str | None | HTML | Author's avatar image URL |
author_link | str | None | HTML | Author's profile URL |
author_information | dict | None | HTML | Author details: name, link, video count, subscriber count |
client.get_video(url, load_html=True) or by calling await video.load_sources("html") afterward). The m3u8 streaming URLs are only available from that source.
Methods & Properties
Download Video download()
no_title=True is set on the config.Parameters
- configuration DownloadConfigHLS — HLS download settings. See Downloading.
Returns
→ bool | DownloadReportGet Author author
Pornstar, Model, or Channel based on the author-link pattern. The source-aware property loads the author link on demand.Returns
→ Pornstar | Model | Channel | NonePornstar
dataclass Inherits from UserHelper → BaseMedia. Represents a pornstar profile. Shared base with Model and User for profile info and video iteration.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The pornstar profile URL |
bio | str | None | Short bio / tagline text |
about | str | None | Extended about section text |
info | dict | None | Structured info fields (e.g., gender, age, location) |
Methods
Get Videos get_videos()
Parameters
- pages int — Number of profile pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default does not eagerly load
htmlorapi.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get Uploads get_uploads()
Parameters
- pages int — Number of upload pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default constructs results without eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get GIFs get_gifs()
Parameters
- pages int — Number of GIF pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default constructs results without eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[GIF], None]Model
dataclass Inherits from UserHelper → BaseMedia. Represents a model profile and inherits get_videos() from UserHelper.
Attributes
Same as Pornstar: url, bio, about, info.
Methods
Get Videos get_videos()
UserHelper.Parameters
- pages int — Number of profile pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default constructs results without eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]User
dataclass Inherits from UserHelper → BaseMedia. Represents a regular user profile and inherits get_videos() from UserHelper.
Attributes
Same as Pornstar: url, bio, about, info.
Methods
Get Videos get_videos()
UserHelper.Parameters
- pages int — Number of profile pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default constructs results without eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Channel
dataclass Inherits from BaseMedia. Represents a production channel with studio-level metadata.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The channel page URL |
name | str | None | Channel display name |
is_award_winner | bool | None | Whether the channel has won awards |
video_views | str | None | Total video views across the channel |
subscribers | str | None | Subscriber count |
total_videos | str | None | Total number of videos |
rank | str | None | Channel rank |
description | str | None | Channel description text |
join_date | str | None | When the channel joined |
website | str | None | External website URL |
user_link | str | None | Associated user profile URL |
Methods
Get Videos get_videos()
Parameters
- pages int — Number of channel pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default constructs results without eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get User get_user()
User object associated with this channel.Returns
→ UserPlaylist
dataclass Inherits from BaseMedia. Represents a video playlist with title, description, tags, and video count. Uses the chunked API endpoint internally for video iteration.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The playlist page URL |
title | str | None | Playlist title |
description | str | None | Playlist description text |
views | str | None | View count |
rating_percent | str | None | Rating percentage |
likes | str | None | Like count |
dislikes | str | None | Dislike count |
video_count | str | None | Total number of videos in the playlist |
unavailable_videos | int | None | Number of hidden / unavailable videos |
tags | dict[str, str] | None | Tag name → URL mapping |
author_link | str | None | Playlist author's profile URL |
token | str | None | Internal token for chunked API requests |
playlist_id | str | None | Extracted playlist numeric ID |
Methods
Get Videos get_videos()
Parameters
- pages int — Number of chunked playlist pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default constructs results without eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get Author get_author()
User who created the playlist.Returns
→ UserAlbum
dataclass Inherits from BaseMedia. Represents a photo album with rating, views, tags, and individual photo download support.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The album page URL |
rating_percentage | str | None | Album rating percentage |
views | str | None | View count |
publish_date | str | None | Publish date string |
tags | dict[str, str] | None | Tag name → URL mapping |
votes | str | None | Vote count string |
author_link | str | None | Album author's profile URL |
Methods
Get Photos get_photos()
url, download_url, rating, and views. Uses ProcessPoolExecutor for parallel HTML parsing across pages.Parameters
- pages int — Required. Number of album pages to fetch
Returns
→ AsyncGenerator[dict, None]Each dict contains: url, download_url, rating, views
Download Photo download_photo()
download_url from get_photos() results.Parameters
- url str — Direct download URL of the photo
- path str — Output file path
Returns
→ boolGet Author author
Pornstar object who authored this album.Returns
→ PornstarGIF
dataclass Inherits from BaseMedia. Represents a single GIF with voting data, source video link, and a direct download URL.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The GIF page URL |
title | str | None | GIF title |
vote_count | str | None | Total vote count |
vote_percentage | str | None | Positive vote percentage |
views | str | None | View count |
publish_date | str | None | Upload date |
thumbnail | str | None | Thumbnail image URL |
content_url | str | None | Direct MP4/WebM download URL |
source_video_url | str | None | URL of the source video this GIF was created from |
tags | dict[str, str] | None | Tag name → URL mapping |
Methods
Download GIF download()
no_title=True.Parameters
- configuration DownloadConfigRAW — RAW download settings. See Downloading.
Returns
→ boolShort
dataclass Inherits from BaseMedia. Represents a Pornhub short-form video with metadata extracted from inline JSON.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The short page URL |
title | str | None | Short title |
video_id | str | None | Internal video ID |
video_key | str | None | Video key identifier |
likes | str | None | Like count |
dislikes | str | None | Dislike count |
favorites | str | None | Favorite count |
comment_count | str | None | Comment count |
is_hd | bool | None | Whether the short is HD |
thumbnail | str | None | Thumbnail image URL |
embed_url | str | None | Embed URL |
author_name | str | None | Author display name |
author_link | str | None | Author profile URL |
avatar | str | None | Author avatar image URL |
video_url | str | None | Link to the full video version |
m3u8_base_url | str | None | Synthesized master m3u8 playlist |
media_definitions | dict | None | Raw media quality definitions |
Methods
Download Short download()
no_title=True.Parameters
- configuration DownloadConfigHLS — HLS download settings. See Downloading.
Returns
→ bool | DownloadReportGet Author get_author()
Pornstar object who created this short.Returns
→ PornstarAccount
Represents the authenticated user account. Access via client.account after calling client.login(). Provides methods for recommendations, history, favorites, feed, and subscriptions.
Attributes
| Attribute | Type | Description |
|---|---|---|
name | str | None | Account username |
avatar | str | None | Avatar image URL |
is_premium | bool | Whether the account has premium status |
user | User | None | Associated User object for the account profile |
from pornhub_api import Client
client = Client(email="user@example.com", password="password")
await client.login()
print(client.account.name) # Username
print(client.account.is_premium) # True/False
# Get recommended videos
async for result in client.account.get_recommended():
if result.succeeded:
video = result.unwrap()
await video.load_sources("html")
print(video.title)
Methods
Get Recommended get_recommended()
Parameters
- pages int — Number of recommendation pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default performs no eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get History get_history()
Parameters
- pages int — Number of history pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default performs no eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get Favorites get_favorites()
Parameters
- pages int — Number of favorites pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default performs no eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get Feed get_feed()
Parameters
- section str — Section to filter:
"videos","photos","posts", etc. - pages int — Number of feed pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default performs no eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get Subscriptions get_subscriptions()
Parameters
- pages int — Number of subscription pages.
- iterator_config IteratorConfig | None — Optional v4 iterator policy; the default performs no eager source loading.
Returns
→ AsyncGenerator[ScrapeResult[User], None]Search & Filtering
The PornHub API offers three distinct search methods with rich filtering options:
Video Search Filters
| Parameter | Values | Description |
|---|---|---|
production_type | "professional", "homemade" | Filter by content type |
sort_by | "mr", "mv", "tr" | Most Recent, Most Viewed, Top Rated |
duration_min | "10", "20", "30" | Minimum duration in minutes |
duration_max | "10", "20", "30" | Maximum duration in minutes |
GIF Search Filters
| Parameter | Values | Description |
|---|---|---|
category | "gay", "transgender" | Category filter (default: straight) |
search_filter | "mr", "mv", "tr" | Most Recent, Most Viewed, Top Rated |
HubTraffic API Filters
| Parameter | Values | Description |
|---|---|---|
category | Any category string | Free-form category filter |
sort_by | "newest", "mostviewed", "rating" | Sort order |
period | "weekly", "monthly", "alltime" | Time period filter |
# Search professional videos, sorted by most viewed
async for result in client.search_videos(
query="blonde",
production_type="professional",
sort_by="mv",
pages=3
):
if result.succeeded:
video = result.unwrap()
await video.load_sources("html")
print(video.title)
# Fast search via HubTraffic API
async for result in client.search_hubtraffic(
query="amateur",
sort_by="newest",
period="weekly"
):
if result.succeeded:
video = result.unwrap()
print(video.title, video.views)
Downloading
The PornHub API uses two download modes depending on the content type:
- HLS (
DownloadConfigHLS) — For Videos and Shorts. Downloads HLS streams with quality selection, threaded segment downloading, resume support, and optional TS→MP4 remuxing. - RAW (
DownloadConfigRAW) — For GIFs and Album photos. Direct file downloads with multi-threaded range request support.
HLS Download (Videos & Shorts)
from base_api import DownloadConfigHLS
config = DownloadConfigHLS(
quality="best", # "best", "half", "worst", or height int (e.g. 720)
path="./downloads", # Output directory or file path
no_title=False, # Auto-append video.title + ".mp4" if False
)
# Must have HTML loaded for m3u8 URLs
video = await client.get_video(url, load_html=True)
success = await video.download(configuration=config)
RAW Download (GIFs & Photos)
from base_api import DownloadConfigRAW
config = DownloadConfigRAW(
quality="best", # "best", "half", "worst", or height int
path="./downloads", # Output directory or file path
no_title=False, # Auto-append title + ".mp4" if False
allow_multipart=True, # Use multi-threaded range requests
max_workers=5 # Number of parallel download threads
)
gif = await client.get_gif(url)
success = await gif.download(configuration=config)
For full details on all download configuration options, refer to the eaf_base_api Documentation.
Pagination & Iterators
Methods like search_videos(), pornstar.get_videos(), channel.get_videos(), and the account iterators yield typed ScrapeResult[T] values. Use succeeded to branch safely or unwrap() to return the item and raise its terminal error on failure:
async for result in client.search_videos("college", pages=2):
if result.succeeded:
video = result.unwrap()
await video.load_sources("html")
print(video.title)
else:
print(result.stage, result.url, result.error)
ScrapeResult
| Attribute | Type | Description |
|---|---|---|
stage | ScrapeStage | Whether the result came from the page or item stage |
url | str | The video URL |
page_index | int | Zero-based source page index |
item_index | int | None | Zero-based item index, or None for a page failure |
attempts | int | Number of attempts used by the yielding stage |
item | T | None | The constructed Video, GIF, or User on success |
error | ScrapeOperationError | None | The typed terminal page or item error on failure |
succeeded | bool | True when error is None |
IteratorConfig, bounded retries, and custom handlers
All iterator-only controls now live in one IteratorConfig. Pornhub's package default uses ErrorMode.SKIP for terminal page failures; a supplied config replaces that behavior, and a bare IteratorConfig instead defaults to ErrorMode.YIELD. A retry policy's max_attempts includes the initial attempt, so this example makes at most three stage attempts per failed page or item. Each stage attempt may itself perform the request retries configured on BaseCore.
Leave page_retry or item_retry as None to derive that stage's bounded policy from the active RuntimeConfig request-attempt and backoff settings; an explicit RetryPolicy overrides it per stage.
Pornhub's default iterator configuration loads no media source eagerly: it constructs objects from listing data. Call await item.load_sources("html") or opt in with load_specific_sources=("html",), as below. Use "api" only when the selected media type supports that loader.
from base_api import ErrorAction, ResultOrder, RetryPolicy, ScrapeErrorContext
from base_api.modules.config import IteratorConfig
async def handle_scrape_error(context: ScrapeErrorContext) -> ErrorAction:
if context.attempt < context.max_attempts:
return ErrorAction.RETRY
return ErrorAction.YIELD
retry = RetryPolicy(
max_attempts=3, base_delay=0.5, multiplier=2.0,
max_delay=4.0, jitter=0.2
)
iterator_config = IteratorConfig(
max_page_concurrency=2,
max_item_concurrency=8,
max_pending_items=16,
order=ResultOrder.ORIGINAL,
load_specific_sources=("html",),
page_retry=retry,
item_retry=retry,
page_error_handler=handle_scrape_error,
item_error_handler=handle_scrape_error,
)
async for result in client.search_videos(
"college", pages=2, iterator_config=iterator_config
):
if result.succeeded:
print(result.unwrap().title)
else:
print(result.stage, result.error)
ScrapeErrorContext supplies stage, url, error, attempt, max_attempts, page_index, and item_index. A handler returns ErrorAction.RETRY, RAISE, YIELD, or SKIP.
The core routes page-stage failures to page_error_handler and item-stage failures to item_error_handler. Assign the same callable to both fields only when both stages should use the same policy; otherwise configure either handler independently.
Error Handling
Source loaders translate request failures into exceptions from pornhub_api.modules.errors. Calls that load media expose ordinary loader failures through base_api.MediaLoadError (or MediaLoadErrors for several sources); inspect original_error/errors as shown. Operations outside media loading, such as login, may still raise package or core exceptions directly.
| Exception | When Raised |
|---|---|
NotFound | Server returned HTTP 404 |
NetworkError | General network request failure (wraps NetworkRequestError) |
BotDetection | Cloudflare or similar bot protection triggered |
ProxyError | Invalid or failing proxy |
UnknownNetworkError | Unexpected network errors |
DownloadFailed | Download operation failed |
LoginFailed | Authentication failed (invalid credentials or token) |
ClientAlreadyLogged | Attempted login when already authenticated |
VideoDisabled | The video has been disabled by the platform |
GifPendingReview | The GIF is still pending review and cannot be accessed |
from base_api import MediaLoadError
from pornhub_api.modules.errors import NotFound, BotDetection, LoginFailed
try:
video = await client.get_video(url, load_html=True, load_api=False)
except MediaLoadError as error:
if isinstance(error.original_error, NotFound):
print("Video does not exist")
elif isinstance(error.original_error, BotDetection):
print("Bypassing bot protection failed")
else:
raise
try:
await client.login()
except LoginFailed as e:
print(f"Login failed: {e}")
CLI Usage
The PornHub API package includes a built-in CLI accessible via the phub command:
# Download a single video
phub --download "https://www.pornhub.com/view_video.php?viewkey=..." --quality best --output ./downloads --no-title False
# Download from a file of URLs
phub --file urls.txt --quality best --output ./downloads --no-title False
# Download liked videos (requires login)
phub --liked --email user@example.com --password pass --quality best --output ./favorites --no-title False
# Download with video ID as filename and a limit
phub --download "https://www.pornhub.com/view_video.php?viewkey=..." --quality best --output ./downloads --no-title False --id-as-title --limit 10
CLI Options
| Flag | Description |
|---|---|
--download URL | Download from the specified URL (video, short, GIF, album, pornstar, model, user, channel, or playlist) |
--file FILE | Read and download URLs from a line-separated text file |
--quality QUALITY | Required. The video quality: best, half, worst |
--output DIR | Required. The destination path/directory |
--no-title True/False | Required. Skip auto-appending video title to output filename |
--pages N | Number of pages to fetch for iterables (default: 1) |
--email EMAIL | Account email for login |
--password PASS | Account password for login |
--id-as-title | Use the video ID as the output filename instead of the title |
--limit N | Maximum number of videos to download |
--liked | Download liked/favorite videos (requires login) |
--recommended | Download recommended videos (requires login) |
--watched | Download watched/history videos (requires login) |
Changelog
5.4 — 2026-08-11
68f6a65/b16c2ea— Sanitized Short, GIF, and Video download titles to prevent path traversal and illegal filenames, then released 5.4.6a5c064— Added genericScrapeStream/ScrapeResulttyping and the PEP 561py.typedmarker; iterator retry fields remain unset so they resolve fromRuntimeConfig.
5.3.1 fixes — 2026-08-10
1acf957— Made iterator source loading opt-in by default, fixed profile/videosURL construction, separated upload/model/playlist extractors for richer structured results and deduplication, tolerated missing playlist descriptions, and corrected count parsing (issues #96, #97, and #98).
5.3.1 iterator synchronization — 2026-08-08
69bffd6— Consolidated iterator concurrency, ordering, source loading, retry, and error controls intoIteratorConfig.
5.3.1 v4 migration — 2026-08-07
7142475— Migrated to the eaf_base_api v4 request and scraping model:fetch_text()/request(), structured exceptions, source-aware media loading, typed scrape streams/results, and bounded retries.
5.3.1 — 2026-08-06
f93c3eb— FixedVideo.author(load_html), corrected the CLI entry point, and released the 5.3.1 patch.
Supported Platforms
| Platform | Architecture | Status |
|---|---|---|
| Windows 11 | x64 | ✅ Tested |
| macOS Sequoia | x86_64 | ✅ Tested |
| Linux (Arch) | x86_64 | ✅ Tested |
| Android 16 | aarch64 | ✅ Tested |