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-hqporner
For CLI formatting support (recommended), install with the optional cli dependency:
pip install unofficial-api-for-hqporner[cli]
eaf-base-api>=4.0.0, which is installed automatically.
Quick Start
Every method in this API is asynchronous. You need to run your code inside an async function:
import asyncio
from hqporner_api import Client
async def main():
client = Client()
# Fetch a video
video = await client.get_video("https://hqporner.com/hd/...")
# Access metadata
print(video.title)
print(video.length)
print(video.pornstars)
# Download the video
from hqporner_api import DownloadConfigRAW
config = DownloadConfigRAW(quality="best", path="./downloads")
await video.download(configuration=config)
asyncio.run(main())
Configuration
The entire API relies on eaf_base_api for its networking. Configure one proxy, timeouts, and request attempts through RuntimeConfig, or pass a custom BaseCore into the Client.
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 hqporner_api import Client
my_config = RuntimeConfig()
my_config.proxy = "socks5://127.0.0.1:9050"
my_config.request_attempts = 4 # Total attempts, including the first request
core = BaseCore(configuration=my_config)
client = Client(core=core)
Iterator, retry, and error policy
Every listing method now accepts one IteratorConfig | None. HQPorner's default eagerly loads "html", skips terminal page failures, and otherwise resolves concurrency and bounded retries from the core's RuntimeConfig.
from base_api import ErrorAction, ErrorMode, ResultOrder, RetryPolicy, ScrapeErrorContext
from base_api.modules.config import IteratorConfig
async def handle_scrape_error(context: ScrapeErrorContext) -> ErrorAction:
print(context.stage, context.url, context.attempt, context.error)
return ErrorAction.RETRY
retry = RetryPolicy(
max_attempts=3, base_delay=0.5, multiplier=2.0, max_delay=8.0, jitter=0.25
)
iterator_config = IteratorConfig(
max_page_concurrency=2,
max_item_concurrency=10,
load_specific_sources=("html",),
order=ResultOrder.ORIGINAL,
page_retry=retry,
item_retry=retry,
page_error_mode=ErrorMode.SKIP,
item_error_mode=ErrorMode.YIELD,
page_error_handler=handle_scrape_error,
item_error_handler=handle_scrape_error,
)
max_attempts includes the first attempt. page_error_handler and item_error_handler are routed independently. This example shares one callable because it intentionally applies the same retry decision to both stages; use separate callables when page and item policy differ. Handlers receive ScrapeErrorContext and return ErrorAction.RETRY, RAISE, YIELD, or SKIP; they cannot create an unbounded retry loop.
Client
The Client class is your entry point for all interactions. It manages the session and headers, providing methods to search, retrieve category lists, and scrape video listings.
Methods
Fetch Video get_video()
Video object. Supports mobile URL fallbacks automatically.Parameters
- url str — The full HQPorner video URL
- load_html bool — If
True(default), fetches and parses the HTML page for metadata
Returns
→ VideoGet Videos by Actress get_videos_by_actress()
Parameters
- name str — The actress name (slug format or full URL)
- pages int — Number of pages to fetch (default:
5) - iterator_config IteratorConfig | None — Concurrency, HTML loading, ordering, retry, and error policy
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get Videos by Category get_videos_by_category()
Parameters
- category Category | str — The category name or Enum member
- pages int — Number of pages to fetch (default:
5) - iterator_config IteratorConfig | None — Concurrency, HTML loading, ordering, retry, and error policy
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Search Videos search_videos()
Parameters
- query str — Search keywords
- pages int — Number of result pages to iterate
- iterator_config IteratorConfig | None — Concurrency, HTML loading, ordering, retry, and error policy
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get Top Videos get_top_porn()
Parameters
- sort_by Sort | str — Sort interval:
Sort.ALL_TIME,Sort.WEEK,Sort.MONTH - pages int — Number of pages to retrieve
- iterator_config IteratorConfig | None — Concurrency, HTML loading, ordering, retry, and error policy
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Get Random Video get_random_video()
Video object.Returns
→ VideoGet All Categories get_all_categories()
Returns
→ list[str]Get Brazzers Videos get_brazzers_videos()
Parameters
- pages int — Number of pages to fetch
- iterator_config IteratorConfig | None — Concurrency, HTML loading, ordering, retry, and error policy
Returns
→ AsyncGenerator[ScrapeResult[Video], None]Video
dataclass Inherits from BaseMedia. Represents a single video with extracted streaming qualities and download links.
Attributes
| Attribute | Type | Description |
|---|---|---|
url | str | The video page URL |
title | str | None | Video title |
cdn_url | str | None | The Altplayer CDN iframe/block URL path |
pornstars | list[str] | None | List of actress names featured in the video |
length | str | None | Video length/duration (e.g., 15:45) |
publish_date | str | None | Upload date string |
tags | list[str] | None | List of category/tag strings |
direct_download_urls | list[str] | None | Resolved direct MP4 links from Altplayer |
thumbnail | str | None | Video preview/thumbnail URL |
Methods & Properties
Available Qualities video_qualities
["360", "480", "720", "1080"]).Returns
→ list[str]Download Video download()
no_title=True. Ordinary failures raise DownloadFailed with full diagnostic context and chained cause.- configuration DownloadConfigRAW — RAW download settings. See Downloading.
Returns
→ boolSearch & Filtering
Perform searches or sort categories using these helper Enums:
from base_api import ResultOrder
from base_api.modules.config import IteratorConfig
from hqporner_api import Category, Sort
async for result in client.get_videos_by_category(
category=Category.QUALITY_4K,
pages=3,
iterator_config=IteratorConfig(
load_specific_sources=("html",),
order=ResultOrder.ORIGINAL,
),
):
if result.succeeded:
print(result.unwrap().title)
Sorting Enums
Sort (Top Lists)
| Enum Value | Description |
|---|---|
Sort.ALL_TIME | All time top videos |
Sort.WEEK | Weekly top videos |
Sort.MONTH | Monthly top videos |
Category (Slugs)
A partial list of available categories within the Category StrEnum (refer to hqporner_api.modules.locals for the full list):
| Enum Member | Slug Value |
|---|---|
Category.QUALITY_HD | "1080p-porn" |
Category.QUALITY_4K | "4k-porn" |
Category.FPS_60 | "60fps-porn" |
Category.MILF | "milf" |
Category.LESBIAN | "lesbian" |
Category.POV | "pov" |
Category.ASIAN | "asian" |
Category.AMATEUR | "amateur" |
Downloading
HQPorner videos host direct MP4 media files instead of HLS streams. All downloads are configured using the DownloadConfigRAW dataclass:
from hqporner_api import DownloadConfigRAW
config = DownloadConfigRAW(
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
allow_multipart=True, # Use multi-threaded range requests
max_workers=5 # Number of parallel download threads
)
success = await video.download(configuration=config)
DownloadConfigRAW — Full Options
| Parameter | Type | Default | Description |
|---|---|---|---|
quality | str | int | — | Required. "best", "half", "worst", or resolution height (360, 480, 720, 1080, etc.) |
path | str | "./" | Output directory or exact file path |
no_title | bool | False | If True, treat path as the exact destination filename |
callback | (int, int) → None | None | Progress callback (downloaded, total) |
stop_event | asyncio.Event | None | Set this event to cancel the download |
allow_multipart | bool | True | Enable parallel segmented downloads using range requests |
max_workers | int | 5 | Maximum concurrent worker threads for downloading segments |
read_timeout | float | 120.0 | Connection read timeout in seconds for chunk fetching |
chunk_size | int | 1024 | Download buffer chunk size in bytes |
max_retries | int | 5 | Max retries per worker when downloading chunks |
Pagination & Iterators
Methods like search_videos(), get_videos_by_actress(), and get_videos_by_category() return async generators yielding immutable ScrapeResult[Video] instances:
async for result in client.search_videos("college", pages=2):
if result.succeeded:
video = result.unwrap()
print(video.title)
else:
print(f"{result.stage} failed for {result.url}: {result.error}")
ScrapeResult
| Attribute | Type | Description |
|---|---|---|
url | str | The video URL |
stage | ScrapeStage | ITEM for media results or PAGE for yielded page failures |
page_index | int | Zero-based page index |
item_index | int | None | Extractor position, or None for a page failure |
attempts | int | Number of stage attempts used |
item | Video | None | The populated Video when successful |
error | ScrapeOperationError | None | The typed page or item failure |
succeeded | bool | True when item is present |
unwrap() | Video | Returns the item or raises the stored typed error |
IteratorConfig Parameters
All iterator methods accept a single iterator_config. The most commonly customized fields are:
- max_item_concurrency int | None — Concurrent Video work;
Noneresolves fromRuntimeConfig.videos_concurrency. - max_page_concurrency int | None — Concurrent page work;
Noneresolves fromRuntimeConfig.pages_concurrency. - load_specific_sources Iterable[str] — Keep
("html",)to preserve HQPorner's populated Video results. - order ResultOrder | str — Completion order by default; use
ResultOrder.ORIGINALfor page/extractor order. - page_retry / item_retry RetryPolicy | None — Bounded stage policies;
Noneresolves from RuntimeConfig. - page_error_handler / item_error_handler ErrorHandler | None — Structured handlers receiving
ScrapeErrorContextand returningErrorAction.
Error Handling
Source loaders translate request failures into exceptions from hqporner_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.
Request and download failures are logged with the operation, target URL, and full original traceback. Translated exceptions retain the original error in __cause__. Download preparation failures (including metadata loading, quality selection, and output path setup) are also wrapped in DownloadFailed; inspect its cause when diagnosing a failure. The specific availability exceptions listed below remain supported. An explicit DownloadCancelled or asyncio.CancelledError propagates without being wrapped in DownloadFailed. Base downloader False and DownloadReport results remain supported; inspect the result as well as handling exceptions.
The common provider errors NotFound, NetworkError, BotDetection, ProxyError, UnknownNetworkError, and DownloadFailed are catchable through base_api.modules.errors. They derive from ScraperException, which now derives from BaseScraperError. Existing provider import paths remain valid.
See Logging & Cleanup for application logging setup.
InvalidActress derives from ScraperException. NotAvailable derives from the shared VideoUnavailable and is still raised directly when no download qualities are available. Both retain their default messages and accept a custom message.
| Exception | When Raised |
|---|---|
InvalidActress | The actress name or URL pattern did not match checks |
NotAvailable | No download qualities are available; this error subclasses VideoUnavailable |
NotFound | Server returned HTTP 404 |
NetworkError | Request failed due to a network error, exhausted request retries, or a non-404 HTTPStatusError |
BotDetection | Bot protection triggered |
ProxyError | Invalid or failing proxy |
UnknownNetworkError | Unexpected network errors |
DownloadFailed | Download preparation or transfer failed; the video URL is included and __cause__ retains the original exception |
from base_api import MediaLoadError
from hqporner_api.modules.errors import NotFound, BotDetection
try:
video = await client.get_video(url)
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
CLI Usage
The CLI entry point configures console logging at INFO level. Caught per-URL failures include the URL and full traceback; the default log format shows the logger, file, line, and function. Library applications should configure logging once at startup.
The HQPorner API package includes a rich CLI accessible via hqporner_api or python -m hqporner_api:
# Download a single video
hqporner_api --download "https://hqporner.com/hd/..." --quality best --output ./downloads --no-title False
# Search and download resulting videos
hqporner_api --search "blonde" --pages 2 --quality 1080 --output ./blonde_videos/ --concurrency 3
CLI Options
| Flag | Description |
|---|---|
--download URL | Download a single video from the specified URL |
--file FILE | Read and download URLs from a line-separated text file |
--search QUERY | Search videos by keyword and download matches |
--actress NAME | Download videos featuring the actress name or URL |
--category CATEGORY | Download videos from a specific category |
--random | Download a single randomly chosen video |
--quality QUALITY | Required. The video quality: best, half, worst, or specific height (e.g. 720) |
--output DIR | Required. The destination path/directory |
--no-title True/False | Skip auto-appending video title to output filename (default: False) |
--pages N | Number of pages to scrape (default: 1) |
--concurrency N | Max concurrent downloads to run in parallel (default: 3) |
Changelog
2.5 (current)
- 2026-09-15 ·
fccc573/4e702e9— Adopted shared request and download error handling withbase_api.modules.provider(requiringeaf-base-api>=4.2.0). Failed downloads now raiseDownloadFailedwith complete diagnostic context. Added layout anchor validations to detect page structure changes. Implemented robust fallback selectors for video metadata and CDN URLs. Enhanced download quality resolution usingPATTERN_RESOLUTIONand validation. Added snippet-based unit tests for HTML extraction and layout checks. - 2026-08-11 ·
a097c19— Released 2.5, added genericScrapeResult[Video]annotations and thepy.typedmarker, and switched missing iterator policies to live RuntimeConfig-derived defaults. - 2026-08-08 ·
e3055d4— Centralized every listing method onIteratorConfig, preserving required("html",)loading and page-failure skipping while removing legacy concurrency/loading/order/callback parameters. - 2026-08-07 ·
eaceacf— Migrated toeaf-base-api>=4.0.0: explicit request methods, source-aware fields/loaders, bounded scheduling, deterministic stream cleanup, structured results/errors, and extractor validation.
Supported Platforms
| Platform | Architecture | Status |
|---|---|---|
| Windows 11 | x64 | ✅ Tested |
| macOS Sequoia | x86_64 | ✅ Tested |
| Linux (Arch) | x86_64 | ✅ Tested |
| Android 16 | aarch64 | ✅ Tested |