Python library for extracting downloadable content metadata from file hosting platforms
Project description
[pkg]: megaloader (core)
Library for extracting downloadable content metadata from file hosting platforms. Provides automatic URL detection and a plugin architecture for multi-platform support.
Installation
pip install megaloader
The library has minimal dependencies: requests for HTTP, beautifulsoup4 and
lxml for HTML parsing.
Basic usage
Call extract() with any supported URL. The function detects the platform
automatically and returns a generator of file metadata:
from megaloader import extract
for item in extract("https://pixeldrain.com/l/abc123"):
print(f"{item.filename} - {item.download_url}")
Each item contains the download URL, filename, and optional metadata like collection name and file size. Network requests happen lazily during iteration.
You can also force a plugin explicitly:
for item in extract("https://example.invalid/path", plugin="gofile"):
print(item.filename)
Downloading files
The library extracts metadata only. Use requests or similar to download:
import requests
from pathlib import Path
from megaloader import extract
def download_file(item, output_dir):
dest = Path(output_dir) / item.filename
response = requests.get(item.download_url, headers=item.headers, stream=True)
response.raise_for_status()
with open(dest, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
for item in extract("https://pixeldrain.com/l/abc123"):
download_file(item, "./downloads")
The headers attribute contains any required HTTP headers for the download
request.
API options
extract() accepts optional transport and plugin controls:
import requests
from megaloader import extract
from megaloader.plugins.gofile import Gofile
session = requests.Session()
# Force plugin by name
items = extract("https://example.invalid/path", plugin="gofile")
# Force plugin by class
items = extract("https://example.invalid/path", plugin=Gofile)
# Inject your own session and timeout
items = extract("https://gofile.io/d/fhGIJu", session=session, timeout=20)
This keeps extraction in core while letting downstream apps decide transport policy.
Supported platforms
Four core platforms receive active development. Seven extended platforms are maintained best-effort and may break without immediate fixes.
Core platforms:
Bunkr (bunkr.si, bunkr.la, bunkr.is, bunkr.ru, bunkr.su), PixelDrain (pixeldrain.com), Cyberdrop (cyberdrop.cr, cyberdrop.me, cyberdrop.to), GoFile (gofile.io).
Extended platforms:
Pixiv (pixiv.net), Rule34 (rule34.xxx), ThotsLife (thotslife.com), ThotHub.VIP (thothub.vip), ThotHub.TO (thothub.to), Fapello (fapello.com).
All platforms support albums, galleries, or lists. Single-file URLs work where applicable.
Platform-specific features
GoFile supports password-protected folders:
items = extract("https://gofile.io/d/folder", password="secret123")
Pixiv requires a session cookie for full results. Without authentication, only public content is returned (which is very limited):
items = extract("https://pixiv.net/artworks/12345", session_id="your_session_cookie")
Rule34 accepts optional API credentials for higher rate limits and faster extraction. Without them, scraping is used as a fallback:
items = extract(
"https://rule34.xxx/index.php?page=post&s=list&tags=example",
api_key="your_api_key",
user_id="your_user_id"
)
[!WARNING]
Free-tier accounts on Pixiv may still return incomplete file sets.
Working with items
The DownloadItem dataclass contains file metadata:
for item in extract(url):
item.download_url # Direct download URL (required)
item.filename # Leaf filename only (required, no path separators)
item.collection_name # Album/gallery name (optional)
item.source_id # Platform-specific ID (optional)
item.size_bytes # File size in bytes (optional)
item.headers # Required HTTP headers (optional)
Required fields are always populated. Optional fields may be None depending on
platform and content type.
Direct plugin usage
Import plugin classes directly when you need plugin-specific control:
from megaloader.plugins.cyberdrop import Cyberdrop
plugin = Cyberdrop("https://cyberdrop.me/a/album_id")
items = list(plugin.extract())
print(f"Found {len(items)} files")
This bypasses automatic detection and gives direct access to plugin internals.
Error handling
Then use commas and make the sentence structurally explicit instead of interruptive.
Best version without em dashes:
All extraction failures surface as typed exceptions. Malformed URLs raise
ValueError. Unknown hosts raise UnsupportedDomainError. All other failures,
including HTTP errors, network failures, and unexpected API responses, raise
ExtractionError with structured metadata:
from megaloader import (
ExtractionError,
UnsupportedDomainError,
extract,
)
try:
items = list(extract(url))
except UnsupportedDomainError:
print("Platform not supported")
except ExtractionError as e:
print(f"Extraction failed: {e.detail}")
print(f"source={e.source} category={e.category} http={e.http_status}")
except ValueError:
print("Invalid URL format")
ExtractionError.category is one of "rate_limit", "auth", "access",
"network", "timeout", "protocol", or "unknown". HTTP status codes are
classified automatically: a 429 always surfaces as "rate_limit", a 401 as
"auth", and so on, regardless of which plugin handled the request.
Writing a plugin
Subclass BasePlugin and implement extract():
from collections.abc import Generator
from megaloader.plugin import BasePlugin
from megaloader.item import DownloadItem
class MyPlugin(BasePlugin):
def _configure_session(self, session):
session.headers["Referer"] = "https://example.com/"
def extract(self) -> Generator[DownloadItem, None, None]:
response = self._get(self.url) # raises ExtractionError on failure
data = response.json()
for file in data["files"]:
yield DownloadItem(
download_url=file["url"],
filename=file["name"],
)
Use self._get(url) and self._post(url, ...) instead of the session directly.
Both methods map HTTP and network failures to ExtractionError automatically,
so extract() only needs to handle business logic. Override
_configure_session() to add authentication headers or cookies.
Contributing
Install dependencies with uv sync from the repository root. Run
mise run check before committing; it covers formatting, type checking, and
unit tests. See the repository contributing guide for plugin development
details.
Report bugs and request features through GitHub Discussions. Include Python version, error messages, and problematic URLs.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file megaloader-0.2.0.tar.gz.
File metadata
- Download URL: megaloader-0.2.0.tar.gz
- Upload date:
- Size: 15.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ec81bac068a0dd4c73c22e1a459b4d6777bd6bb1f6aa83a51b55a33e1b16ecc
|
|
| MD5 |
72863f4ab2982715c2998c233f7334b2
|
|
| BLAKE2b-256 |
ff6d514ab3d4b74751a20af2b7144836e360d70af5209596acb4c1e7402fd4f2
|
Provenance
The following attestation bundles were made for megaloader-0.2.0.tar.gz:
Publisher:
release-core.yml on totallynotdavid/megaloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
megaloader-0.2.0.tar.gz -
Subject digest:
4ec81bac068a0dd4c73c22e1a459b4d6777bd6bb1f6aa83a51b55a33e1b16ecc - Sigstore transparency entry: 1810698191
- Sigstore integration time:
-
Permalink:
totallynotdavid/megaloader@ab6b7cb28b22009eff803b9cdc2b8973acc13876 -
Branch / Tag:
refs/tags/vcore-0.2.0 - Owner: https://github.com/totallynotdavid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-core.yml@ab6b7cb28b22009eff803b9cdc2b8973acc13876 -
Trigger Event:
push
-
Statement type:
File details
Details for the file megaloader-0.2.0-py3-none-any.whl.
File metadata
- Download URL: megaloader-0.2.0-py3-none-any.whl
- Upload date:
- Size: 30.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c4cb13e2090200649e1c1db9cabac511c918ac856a8999b91010db8d36a01fa
|
|
| MD5 |
546aedd0bc081c813fe23b490c38f087
|
|
| BLAKE2b-256 |
02532c643bcc2eb75a0f5b37bfb3b8e4e5e815125ee1a76d309d006c33c96e38
|
Provenance
The following attestation bundles were made for megaloader-0.2.0-py3-none-any.whl:
Publisher:
release-core.yml on totallynotdavid/megaloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
megaloader-0.2.0-py3-none-any.whl -
Subject digest:
2c4cb13e2090200649e1c1db9cabac511c918ac856a8999b91010db8d36a01fa - Sigstore transparency entry: 1810698214
- Sigstore integration time:
-
Permalink:
totallynotdavid/megaloader@ab6b7cb28b22009eff803b9cdc2b8973acc13876 -
Branch / Tag:
refs/tags/vcore-0.2.0 - Owner: https://github.com/totallynotdavid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-core.yml@ab6b7cb28b22009eff803b9cdc2b8973acc13876 -
Trigger Event:
push
-
Statement type: