| name | webtoon-vault-manga-downloader |
| description | CLI tool for downloading manga and webcomics from multiple hosting platforms with intelligent parsing and CBZ packaging |
| triggers | ["download manga chapters from a URL","scrape webcomics into CBZ format","batch download manga series offline","extract comic pages from hosting platforms","create offline manga library archive","pull chapters from manga websites","harvest webcomic images with metadata","automate comic book downloads"] |
Webtoon Vault Manga Downloader
Skill by ara.so — Devtools Skills collection.
A sophisticated CLI tool for downloading manga and webcomics from multiple hosting platforms. Features intelligent source detection, parallel chapter fetching, CBZ archive creation, and multi-platform parser support for offline comic reading.
What It Does
Webtoon Vault automates the extraction of manga/webcomic chapters from various hosting platforms and packages them into organized CBZ archives or directory structures. Key capabilities:
- Auto-detection of source platform from URL patterns
- Parallel downloads with async I/O for speed
- CBZ packaging with embedded metadata
- Resume support for interrupted downloads
- Multi-language metadata extraction
- Rate limiting to respect server constraints
Supported platforms include Mori Manga, DuManWu, KanKanManHua, ManhuaDB, and GuFeng.
Installation
The project is HTML-based with a web download interface. Based on the repository structure, the actual Python CLI tool is distributed through the GitHub Pages site:
unzip webtoon-vault.zip
cd webtoon-vault
pip install -r requirements.txt
pip install webtoon-vault
For development/testing from source:
git clone https://github.com/BunaTechnologyBackUP/manga-pull-cli.git
cd manga-pull-cli
pip install -e .
Core CLI Commands
Basic Download
Download a single series from a URL:
webtoon-vault download "https://mhpic.com/comic/one-piece"
webtoon-vault download "https://dumanwu.com/series/jujutsu-kaisen" --output ./manga/
webtoon-vault download "https://kankanmanhua.com/comic/naruto" --chapters 1-50
webtoon-vault download "https://manhuadb.com/series/bleach" --format images
Advanced Options
webtoon-vault download URL --parallel 5
webtoon-vault download URL --dry-run
webtoon-vault download URL --verbose
webtoon-vault download URL --template "{series}_Vol{volume}_Ch{chapter}"
webtoon-vault download URL --proxy http://proxy.example.com:8080
webtoon-vault resume ./manga/one-piece/
webtoon-vault platforms
Batch Operations
webtoon-vault batch urls.txt --output ./comics/
Configuration
Config File (~/.webtoon-vault/config.json)
{
"output_dir": "~/Comics",
"format": "cbz",
"parallel_downloads": 3,
"naming_template": "{series}_ch{chapter:03d}",
"rate_limit_delay": 1.5,
"max_retries": 5,
"user_agents": [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
],
"proxy": null,
"verify_ssl": true,
"compress_images": false
}
Environment Variables
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
export WEBTOON_VAULT_OUTPUT=~/my-manga-library
export WEBTOON_VAULT_USER_AGENT="MyReader/1.0"
export WEBTOON_VAULT_DEBUG=1
Python API Usage
While primarily a CLI tool, the core functionality can be used programmatically:
from webtoon_vault import Downloader, PlatformDetector
from pathlib import Path
downloader = Downloader(
output_dir=Path("./manga"),
format="cbz",
parallel_limit=3
)
url = "https://mhpic.com/comic/one-piece"
result = downloader.download(url, chapters=range(1, 10))
print(f"Downloaded {result.chapters_downloaded} chapters")
print(f"Total size: {result.total_bytes / 1024 / 1024:.2f} MB")
Custom Platform Parser
from webtoon_vault.parsers import BaseParser
import re
class CustomSiteParser(BaseParser):
"""Parser for custom manga site"""
DOMAIN_PATTERN = re.compile(r'customsite\.com')
def get_chapter_list(self, series_url):
"""Extract all chapter URLs from series page"""
response = self.session.get(series_url)
soup = BeautifulSoup(response.text, 'html.parser')
chapters = []
for link in soup.select('.chapter-link'):
chapters.append({
'url': link['href'],
'title': link.text.strip(),
'number': self._extract_chapter_number(link.text)
})
return chapters
def get_chapter_images(self, chapter_url):
"""Extract all image URLs from chapter page"""
response = self.session.get(chapter_url)
soup = BeautifulSoup(response.text, 'html.parser')
images = []
for img in soup.select('.manga-page img'):
images.append(img['src'])
return images
from webtoon_vault import register_parser
register_parser(CustomSiteParser)
Async Batch Download
import asyncio
from webtoon_vault import AsyncDownloader
async def batch_download():
downloader = AsyncDownloader(
output_dir="./comics",
concurrent_chapters=5
)
urls = [
"https://mhpic.com/comic/one-piece",
"https://dumanwu.com/series/naruto",
"https://kankanmanhua.com/comic/bleach"
]
results = await downloader.download_batch(urls)
for url, result in zip(urls, results):
if result.success:
print(f"✓ {url}: {result.chapters_downloaded} chapters")
else:
print(f"✗ {url}: {result.error}")
asyncio.run(batch_download())
Common Patterns
Building Offline Library
from webtoon_vault import LibraryManager
from pathlib import Path
library = LibraryManager(base_dir=Path("~/Comics"))
series_urls = [
"https://mhpic.com/comic/one-piece",
"https://dumanwu.com/series/attack-on-titan"
]
for url in series_urls:
series = library.add_series(url)
library.download_series(series, format="cbz")
library.update_metadata(series)
all_series = library.list_series()
incomplete = library.find_incomplete_series()
library.export_catalog("catalog.json")
Chapter Range Download
from webtoon_vault import Downloader
downloader = Downloader(output_dir="./manga")
url = "https://mhpic.com/comic/one-piece"
downloader.download(url, chapters=range(1, 101))
downloader.download(url, chapters=[1, 5, 10, 15, 20])
downloader.download(url, latest=10)
Resume Interrupted Downloads
from webtoon_vault import ResumeManager
resume = ResumeManager()
try:
downloader.download(url)
except KeyboardInterrupt:
resume.save_state(downloader.get_state())
state = resume.load_state()
if state:
downloader.restore_state(state)
downloader.continue_download()
Custom Naming and Organization
from webtoon_vault import Downloader, NamingTemplate
template = NamingTemplate(
pattern="{series}/{volume:02d}/{series}_v{volume:02d}_ch{chapter:03d}",
metadata_fields=['series', 'volume', 'chapter', 'title']
)
downloader = Downloader(
output_dir="./library",
naming_template=template
)
Rate Limiting and Retry Logic
from webtoon_vault import Downloader, RateLimiter
limiter = RateLimiter(
requests_per_second=2,
burst_size=5,
backoff_factor=2.0,
max_delay=30
)
downloader = Downloader(
rate_limiter=limiter,
max_retries=5,
retry_delay=3
)
result = downloader.download(
url,
on_error='retry',
verify_checksums=True
)
Troubleshooting
Platform Detection Fails
from webtoon_vault import Downloader
from webtoon_vault.parsers import MoriMangaParser
downloader = Downloader(parser=MoriMangaParser)
downloader.download(url)
SSL Certificate Errors
webtoon-vault download URL --no-verify-ssl
Or in code:
downloader = Downloader(verify_ssl=False)
Rate Limit / IP Blocking
webtoon-vault download URL --delay 3.0
webtoon-vault download URL --rotate-user-agents
webtoon-vault download URL --proxy socks5://proxy.example.com:1080
Images Not Loading (Lazy Loading)
from webtoon_vault import Downloader
downloader = Downloader(
use_selenium=True,
browser='chrome',
headless=True
)
Memory Issues with Large Series
downloader = Downloader(
stream_mode=True,
chunk_size=8192,
max_memory_mb=512
)
Debug Failed Downloads
import logging
from webtoon_vault import Downloader
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('webtoon_vault')
downloader = Downloader(logger=logger)
result = downloader.download(url)
for failure in result.failed_chapters:
print(f"Chapter {failure.number}: {failure.error}")
print(f"Traceback: {failure.traceback}")
Corrupted CBZ Files
webtoon-vault verify ./manga/one-piece/ --repair
webtoon-vault redownload ./manga/one-piece/ --verify-checksums
Best Practices
- Respect rate limits: Use appropriate delays to avoid IP bans
- Resume support: Always enable session caching for large downloads
- Verify downloads: Use checksum verification for critical archives
- Organize early: Set up naming templates before downloading
- Monitor disk space: Large series can consume significant storage
- Keep user agents updated: Rotate UAs to avoid detection
- Handle errors gracefully: Use retry logic with exponential backoff
- Legal compliance: Only download content you have rights to access
Platform-Specific Notes
Mori Manga (mhpic.com)
- Supports lazy-loaded images
- Requires JavaScript rendering for some series
- Rate limit: ~2 requests/second recommended
DuManWu
- Uses dynamic chapter pagination
- Image URLs expire after 1 hour
- Best with parallel downloads enabled
KanKanManHua
- Implements anti-scraping tokens
- Requires cookie injection for age-gated content
- User-Agent rotation recommended
ManhuaDB (Beta)
- Inconsistent chapter numbering
- Manual verification recommended
- May require custom parsers for some series