npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@weroperking/invenio-scraper

v2.0.0

Published

invenio-scraper - A web scraping library for extracting movie and TV show data

Downloads

51

Readme

🎬 @weroperking/invenio-scraper

npm version License: ISC Node.js TypeScript

@weroperking/invenio-scraper - A web scraping library for extracting movie and TV show data

A resilient, fully-typed JavaScript SDK for interacting with Moviebox APIs.

✨ Features

  • 🔍 Search — Find movies, TV series, and music with filtering and pagination
  • 🎥 Details — Get full metadata including ratings, subtitles, and quality options
  • 📡 Streaming — Extract direct stream URLs with quality selection
  • ⬇️ Downloads — Parallel chunked downloads with resume support and progress tracking
  • 🔄 Session Management — Automatic mirror fallback (7 mirrors), retry policies, cookie handling
  • 🌐 Proxy Support — HTTP/HTTPS/SOCKS proxy routing via undici
  • 📦 Pure ESM — Modern JavaScript module format with tree-shaking support
  • 🛡️ Fully Typed — Complete TypeScript type definitions included

📦 Installation

npm install @weroperking/invenio-scraper
pnpm add @weroperking/invenio-scraper
yarn add @weroperking/invenio-scraper

Requirements: Node.js 18+

🚀 Quick Start

import {
  MovieboxSession,
  search,
  getMovieDetails,
  getMovieStreamUrl
} from '@weroperking/invenio-scraper';

async function main(): Promise<void> {
  const session = new MovieboxSession();

  // Search for content
  const results = await search(session, { query: 'Inception' });
  const first = results.results[0];

  if (first) {
    // Get detailed movie information
    const details = await getMovieDetails(session, {
      detailPath: first.raw.detailPath
    });

    // Get stream URL
    const stream = await getMovieStreamUrl(session, {
      detailPath: first.raw.detailPath,
      quality: 'best'
    });

    console.log(`${details.title}: ${stream.stream?.url}`);
  }
}

main().catch((error) => {
  console.error('Error:', error);
  process.exit(1);
});

🏃 Running TypeScript Files

This SDK is written in TypeScript. To run TypeScript files directly, use tsx:

# Install tsx globally
npm install -g tsx

# Or add to your project
npm install -D tsx

# Run a TypeScript file
tsx your-script.ts

Alternatively, you can compile TypeScript to JavaScript using tsc and run with node:

# Compile TypeScript
npx tsc your-script.ts

# Run the compiled JavaScript
node your-script.js

📚 API Overview

| Capability | Function | Description | |------------|----------|-------------| | 🔍 Search | search(session, params) | Search movies, series, and music | | 🎬 Movie Details | getMovieDetails(session, params) | Get full movie metadata | | 📺 Series Details | getSeriesDetails(session, params) | Get series metadata & seasons | | 📺 Episode Qualities | getEpisodeQualities(session, params) | Get episode download options | | 📡 Movie Stream | getMovieStreamUrl(session, params) | Extract movie stream URL | | 📡 Episode Stream | getEpisodeStreamUrl(session, params) | Extract episode stream URL | | ⬇️ Movie Download | downloadMovie(session, params) | Download a movie file | | ⬇️ Episode Download | downloadEpisode(session, params) | Download an episode file | | ⬇️ Media Download | downloadMediaFile(session, option, destination, options) | Download with progress tracking |

⚙️ Configuration

Session Options

import { MovieboxSession, createLogger } from '@weroperking/invenio-scraper';

const session = new MovieboxSession({
  host: 'h5.aoneroom.com',
  mirrorHosts: ['h5.aoneroom.com', 'movieboxapp.in'],
  proxyUrl: process.env.INVENIO_API_PROXY,
  logger: createLogger({ level: 'info' }),
  retry: {
    maxAttempts: 3,
    delayMs: 500
  }
});

Options Table

| Option | Type | Default | Description | |--------|------|---------|-------------| | host | string | First mirror | Primary API host | | mirrorHosts | readonly string[] | 7 built-in mirrors | List of fallback mirrors | | protocol | 'http' \| 'https' | 'https' | Protocol to use | | proxyUrl | string | — | HTTP/HTTPS/SOCKS proxy URL | | logger | Logger | No-op logger | Custom logger instance | | retry.maxAttempts | number | 2 | Maximum retry attempts | | retry.delayMs | number | 200 | Delay between retries (ms) | | defaultHeaders | HeadersInit | Built-in headers | Custom request headers |

Environment Variables

| Variable | Description | |----------|-------------| | INVENIO_API_HOST | Override the default mirror host | | INVENIO_API_PROXY | Route requests through an HTTP/S/SOCKS proxy |

📖 Usage Examples

Basic Search

import { MovieboxSession, search } from '@weroperking/invenio-scraper';

async function main(): Promise<void> {
  const session = new MovieboxSession();

  // Search with filters
  const results = await search(session, {
    query: 'The Matrix',
    type: 'movie', // 'all' | 'movie' | 'tv' | 'music'
    page: 1,
    perPage: 20
  });

  console.log(`Found ${results.totalCount} results`);
  console.log(`Has more: ${results.hasMore}`);

  for (const item of results.results) {
    console.log(`${item.title} (${item.releaseYear ?? 'N/A'}) - ${item.rating}/10`);
  }
}

main().catch((error) => {
  console.error('Error:', error);
  process.exit(1);
});

Getting Movie Details

import { MovieboxSession, getMovieDetails } from '@weroperking/invenio-scraper';

async function main(): Promise<void> {
  const session = new MovieboxSession();

  const details = await getMovieDetails(session, {
    detailPath: 'inception-e1BOR6f19C7'
  });

  console.log(`Title: ${details.title}`);
  console.log(`Synopsis: ${details.synopsis}`);
  console.log(`Rating: ${details.rating}/10 (${details.ratingCount} votes)`);
  console.log(`Duration: ${details.durationLabel}`);
  console.log(`Genres: ${details.genres.join(', ')}`);

  // Available download qualities
  for (const download of details.downloads) {
    console.log(`${download.quality}: ${(download.sizeBytes / 1024 / 1024).toFixed(1)} MB`);
  }

  // Available subtitles
  for (const caption of details.captions) {
    console.log(`Subtitle: ${caption.language}`);
  }
}

main().catch((error) => {
  console.error('Error:', error);
  process.exit(1);
});

Downloading with Progress

import { MovieboxSession, downloadMovie } from '@weroperking/invenio-scraper';

async function main(): Promise<void> {
  const session = new MovieboxSession();

  const filePath = await downloadMovie(session, {
    detailPath: 'inception-e1BOR6f19C7',
    quality: 1080, // or 'best' | 'worst' | number
    outputDir: './downloads',
    mode: 'resume', // 'auto' | 'resume' | 'overwrite'
    onProgress: ({ downloadedBytes, totalBytes, percentage }) => {
      const mb = (downloadedBytes / 1024 / 1024).toFixed(1);
      const total = ((totalBytes ?? 0) / 1024 / 1024).toFixed(1);
      process.stdout.write(`\r${mb}MB / ${total}MB (${percentage ?? 0}%)`);
    }
  });

  console.log(`\nSaved to: ${filePath}`);
}

main().catch((error) => {
  console.error('Error:', error);
  process.exit(1);
});

Series & Episodes

import {
  MovieboxSession,
  search,
  getSeriesDetails,
  getEpisodeQualities,
  getEpisodeStreamUrl,
  downloadEpisode
} from '@weroperking/invenio-scraper';

async function main(): Promise<void> {
  const session = new MovieboxSession();

  // Search for a series
  const results = await search(session, { query: 'Breaking Bad', type: 'tv' });
  const series = results.results.find(r => r.type === 'tv');

  if (series) {
    // Get series details
    const details = await getSeriesDetails(session, {
      detailPath: series.raw.detailPath
    });

    console.log(`${details.title} — ${details.seasons?.length} seasons`);

    // Get episode qualities
    const qualities = await getEpisodeQualities(session, {
      detailPath: series.raw.detailPath,
      season: 1,
      episode: 1
    });

    console.log('Available qualities:', qualities.downloads.map(d => d.quality));

    // Get stream URL
    const stream = await getEpisodeStreamUrl(session, {
      detailPath: series.raw.detailPath,
      season: 1,
      episode: 1,
      quality: 'best'
    });

    console.log('Stream URL:', stream.stream?.url);

    // Download episode
    const filePath = await downloadEpisode(session, {
      detailPath: series.raw.detailPath,
      season: 1,
      episode: 1,
      quality: 720,
      outputDir: './downloads'
    });

    console.log('Downloaded:', filePath);
  }
}

main().catch((error) => {
  console.error('Error:', error);
  process.exit(1);
});

Proxy Configuration

import { MovieboxSession } from '@weroperking/invenio-scraper';

// HTTP proxy
const session = new MovieboxSession({
  proxyUrl: 'http://proxy.example.com:8080'
});

// SOCKS5 proxy
const sessionWithSocks = new MovieboxSession({
  proxyUrl: 'socks5://user:[email protected]:1080'
});

// Or use environment variable
// INVENIO_API_PROXY=socks5://proxy.example.com:1080

See docs/proxy.md for detailed proxy configuration.

Error Handling

import {
  MovieboxSession,
  search,
  MovieboxApiError,
  MovieboxHttpError,
  GeoBlockedError,
  MirrorExhaustedError,
  RetryLimitExceededError
} from '@weroperking/invenio-scraper';

async function main(): Promise<void> {
  const session = new MovieboxSession();

  try {
    const results = await search(session, { query: 'Inception' });
    console.log(`Found ${results.totalCount} results`);
  } catch (error) {
    if (error instanceof GeoBlockedError) {
      console.error('Content is geo-blocked in your region');
    } else if (error instanceof MirrorExhaustedError) {
      console.error('All mirrors failed:', error.failures);
    } else if (error instanceof RetryLimitExceededError) {
      console.error(`Failed after ${error.attempts} attempts`);
    } else if (error instanceof MovieboxHttpError) {
      console.error(`HTTP ${error.status} error for ${error.url}`);
    } else if (error instanceof MovieboxApiError) {
      console.error('API error:', error.message);
    }
  }
}

main().catch((error) => {
  console.error('Error:', error);
  process.exit(1);
});

Custom Logger

import { MovieboxSession, createLogger, createNoopLogger } from '@weroperking/invenio-scraper';

// Enable logging
const session = new MovieboxSession({
  logger: createLogger({ level: 'debug' })
});

// Disable logging (default)
const silentSession = new MovieboxSession({
  logger: createNoopLogger()
});

🛡️ Error Classes

| Error Class | Description | |-------------|-------------| | MovieboxApiError | Base error class for all SDK errors | | MovieboxHttpError | HTTP errors with status code and URL | | EmptyResponseError | API returned an empty response | | UnsuccessfulResponseError | API reported failure in response | | GeoBlockedError | Content not available in region | | MirrorExhaustedError | All mirror hosts failed | | RetryLimitExceededError | Maximum retry attempts exceeded |

📘 TypeScript Support

This SDK is written in TypeScript and provides full type definitions. All types are exported:

import type {
  SearchParams,
  SearchResultPage,
  NormalizedSearchResult,
  MovieDetails,
  SeriesDetails,
  EpisodeQualities,
  StreamResult,
  DownloadProgress,
  Logger
} from '@weroperking/invenio-scraper';

📄 Documentation

🤝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Run checks: pnpm lint && pnpm test
  4. Commit your changes (git commit -m 'Add amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

Please include tests and update fixtures when applicable.

🛠️ Development

# Install dependencies
pnpm install

# Build the project
pnpm build

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Lint code
pnpm lint

# Format code
pnpm format

# Type check
pnpm typecheck

📜 License

This project is licensed under the ISC License.