Thumbzilla API
A fully asynchronous Python API wrapper and scraper for Thumbzilla. Fetch video metadata, playlists, pornstar biographies, amateur profiles, and studio channels. Stream downloads via HLS with auto-constructed master playlists. 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-thumbzilla
For TS→MP4 remuxing support (recommended for HLS downloads), install with the optional av dependency:
pip install unofficial-api-for-thumbzilla[av]
eaf_base_api ≥ 4.0.0, which is installed automatically.
Quick Start
import asyncio
from thumbzilla_api import Client
from base_api import DownloadConfigHLS
async def main():
client = Client()
# Fetch video metadata
video = await client.get_video("https://www.thumbzilla.com/watch/12345")
print(video.title)
print(video.views)
# Download video via HLS
config = DownloadConfigHLS(quality="best", path="./downloads")
await video.download(configuration=config)
asyncio.run(main())
Configuration
Proxy/interface, timeout, request-attempt/delay, cache, and concurrency settings are handled via RuntimeConfig passed to BaseCore.
Please refer to the eaf_base_api Documentation for details.
from base_api import BaseCore
from base_api.modules.config import RuntimeConfig
from thumbzilla_api import Client
my_config = RuntimeConfig()
my_config.proxy = "socks5://127.0.0.1:9050"
my_config.request_attempts = 4
my_config.videos_concurrency = 8
my_config.pages_concurrency = 2
core = BaseCore(configuration=my_config)
client = Client(core=core)
Client
Main entry point class to execute searches and load resource models.
from thumbzilla_api import Client
client = Client()
Constructor Parameters
- core BaseCore — Networking core instance (default:
BaseCore())
Methods
Fetch Video get_video()
Video object.Parameters
- url str — The Thumbzilla video URL
- load_html bool — Pre-load parsed properties immediately
Returns
→ VideoFetch Pornstar get_pornstar()
Pornstar object.Parameters
- url str — The pornstar profile URL
- load_html bool — Pre-load parsed properties
Returns
→ PornstarFetch Playlist get_playlist()
Playlist object.Parameters
- url str — The Thumbzilla playlist URL
- load_html bool — Pre-load parsed properties
Returns
→ PlaylistFetch Channel get_channel()
Parameters
- url str — The channel page URL
- load_html bool — Pre-load parsed properties
Returns
→ ChannelFetch Amateur get_amateur()
Parameters
- url str — The amateur profile page URL
- load_html bool — Pre-load parsed properties
Returns
→ AmateurSearch Videos search()
Parameters
- query str — Search query words
- pages int — Number of search pages to parse
- iterator_configuration IteratorConfig | None — Concurrency, ordering, source loading, retry, and terminal-error policy. The package default loads the
htmlsource.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Video
dataclass Inherits from BaseMedia. Represents a single video with metadata extracted from LD+JSON structured data and JavaScript media definitions.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The video page URL |
video_id | str | None | Unique video key ID |
title | str | None | Video title |
duration | str | int | None | Video duration in seconds |
thumbnail | str | None | Thumbnail cover image URL |
embed_url | str | None | Embeddable player URL |
views | str | None | View count |
publish_date | str | None | Upload date |
publish_date_thumbnail | str | None | Thumbnail publication date |
description | str | None | Video description |
author_name | str | None | Name of the uploader |
m3u8_url | str | None | External HLS variants JSON source URL |
m3u8_base_url | str | None | Auto-constructed HLS master playlist string |
media_definitions | list[dict] | None | Raw media definition configurations |
preview_video_url | str | None | Preview clip path |
performers | list[str] | None | Featured performer names |
uploader_url | str | None | Uploader profile URL |
Methods
Download Video download()
no_title=True.Parameters
- configuration DownloadConfigHLS — HLS download configurations
Returns
→ bool | DownloadReportPlaylist
dataclass Inherits from BaseMedia. Represents a user-curated playlist.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The playlist URL |
title | str | None | Playlist title |
author_name | str | None | Name of the author |
rating_percent | str | None | User rating percentage |
rating_count | str | None | Total rating count |
views | str | None | Number of playlist views |
videos_count | str | None | Total videos count |
Methods
Get Playlist Videos get_videos()
Parameters
- pages int — Pages to load
- iterator_config IteratorConfig | None — Complete iterator policy. The package default loads the
htmlsource.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]User / Pornstar / Amateur
Scraper objects representing creators, actors, and registered users share a common base class (UserHelper).
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | Profile page URL |
name | str | None | Username / profile display name |
pornstar_information | dict | None | Sidebar stat parameters (only populated for Pornstar objects) |
Methods
Get Profile Videos get_videos()
Parameters
- pages int — Pages to load
- iterator_configuration IteratorConfig | None — Complete iterator policy. The package default loads the
htmlsource.
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Channel
dataclass Inherits from UserHelper. Represents a publisher studio channel page.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | Channel page URL |
name | str | None | Studio/channel display name |
rank | str | None | Channel ranking score |
views | str | None | Total channel views count |
videos_count | str | None | Total uploaded videos count |
Methods
Get Channel Videos get_videos()
UserHelper.get_videos().Returns
→ AsyncGenerator[ScrapeResult[Video], None]Downloading Options
Thumbzilla serves video files via HLS streaming. The scraper auto-constructs a master M3U8 playlist from the JSON media definitions. Configure stream downloading parameters via the DownloadConfigHLS class:
from base_api import DownloadConfigHLS
config = DownloadConfigHLS(
quality="best",
path="./downloads",
no_title=False,
return_report=True
)
report = await video.download(configuration=config)
For more configurations, see the shared eaf_base_api Documentation.
Scraping Results
All concurrently iterated methods accept one IteratorConfig policy and yield immutable ScrapeResult[Video] values. The package default loads html and skips terminal page failures. A supplied configuration replaces that default, so include load_specific_sources=("html",) and page_error_mode=ErrorMode.SKIP when preserving both behaviors; the example below deliberately opts into yielding page failures.
The public configuration fields are max_page_concurrency, max_item_concurrency, max_pending_items, extract_in_thread, order, both *_error_mode, both *_retry, both *_error_handler, load_specific_fields, and load_specific_sources.
from base_api import ErrorAction, ErrorMode, ResultOrder, RetryPolicy, ScrapeErrorContext
from base_api.modules.config import IteratorConfig
async def handle_error(context: ScrapeErrorContext) -> ErrorAction:
if context.attempt < context.max_attempts:
return ErrorAction.RETRY
return ErrorAction.YIELD
iterator_config = IteratorConfig(
max_page_concurrency=2,
max_item_concurrency=8,
order=ResultOrder.ORIGINAL,
load_specific_sources=("html",),
page_retry=RetryPolicy(max_attempts=4, base_delay=0.5, jitter=0.25),
item_retry=RetryPolicy(max_attempts=4, base_delay=0.5, jitter=0.25),
page_error_mode=ErrorMode.YIELD,
item_error_mode=ErrorMode.YIELD,
page_error_handler=handle_error,
item_error_handler=handle_error,
)
async for result in pornstar.get_videos(
pages=3, iterator_configuration=iterator_config
):
if result.succeeded:
video = result.unwrap()
print(video.title)
else:
print(result.stage, result.url, result.attempts, result.error)
ScrapeErrorContext(stage, url, error, attempt, max_attempts, page_index, item_index) and returns ErrorAction.RETRY, RAISE, YIELD, or SKIP. RetryPolicy exposes max_attempts, base_delay, multiplier, max_delay, jitter, and retry_for; attempts include the first call. If no retry policy is supplied, it is resolved from RuntimeConfig.request_* values.
ScrapeResult Attributes
| Attribute | Type | Description |
|---|---|---|
stage | ScrapeStage | PAGE or ITEM |
url | str | The page or item target URL |
page_index | int | Zero-based source-page index |
item_index | int | None | Zero-based item index; None for page failures |
attempts | int | Number of attempts consumed |
item | Video | None | The loaded item on success |
error | ScrapeOperationError | None | The typed terminal error on failure |
succeeded | bool | True when the result contains an item |
unwrap() | Video | Returns the item or raises its terminal error |
Error Handling
Source loaders translate request failures into exceptions from thumbzilla_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 may still raise package or core exceptions directly.
| Exception | Trigger Cause |
|---|---|
NotFound | Server returned HTTP 404 (e.g. video deleted) |
NetworkError | Request failed due to HTTP connection problems |
BotDetection | Anti-bot challenge block detected |
ProxyError | Proxy configuration failed or proxy is down |
UnknownNetworkError | Unexpected network errors |
DownloadFailed | HLS segmented stream download failed |
from base_api import MediaLoadError
from thumbzilla_api.modules.errors import NotFound, BotDetection
try:
video = await client.get_video(url)
except MediaLoadError as error:
if isinstance(error.original_error, NotFound):
print("This video does not exist!")
elif isinstance(error.original_error, BotDetection):
print("Scraper was blocked by anti-bot measures.")
else:
raise
Supported Platforms
| Platform | Architecture | Status |
|---|---|---|
| Windows 11 | x64 | ✅ Tested |
| macOS Sequoia | x86_64 / arm64 | ✅ Tested |
| Linux (Arch) | x86_64 | ✅ Tested |
| Android 16 | aarch64 | ✅ Tested |
Changelog
| Date | Commit | Changes |
|---|---|---|
| 2026-08-11 | 0d65160 | Released 1.4 with complete type hints and the py.typed marker. |
| 2026-08-08 | b495027 | Centralized iterator behavior on IteratorConfig, forwarded source/retry defaults, and aligned download-test behavior. |
| 2026-08-08 | e91bdf3 | Synchronized the package with the local eaf v4 source and released 1.3. |
| 2026-08-07 | b2c7678 | Migrated models, explicit source loading, structured retries, and iterator results to eaf v4. |