Project Minato
Scrapers

Skit SDK

API reference for @minato/skit, the TypeScript SDK for Minato scrapers.

Factory functions

import { defineScheduledScraper, defineDaemonScraper } from "@minato/skit";

Export the result as your module's default export.

FunctionUse when
defineScheduledScraperrun() does one pass and exits
defineDaemonScraperrun() maintains a persistent connection

Pass TConfig as a type parameter to type your config:

type Config = { maxPages: number; delayMs: number };
export default defineScheduledScraper<Config>({ ... });

Context

run() receives a single context object:

PropertyTypeDescription
ingestIngestClientBuffer and flush torrents
configTConfigMerged config (dashboard overrides applied)
signalAbortSignalAborted on pause or stop
statusStatusReporterReport progress to the dashboard
meta{ id, name, version }Scraper identity
flaresolverrFlareSolverrPre-configured Cloudflare bypass client

ingest

ingest.add(torrent: TorrentInput): void

Buffers a torrent. Minato flushes in batches automatically; you never call flush() yourself. infoHash is the global deduplication key: the same hash is never stored twice, regardless of which scraper submitted it.

TorrentInput

FieldRequiredTypeNotes
infoHashstring40-char hex info hash
titlestringRelease name
sizenumberTotal size in bytes
source.namestringLabel shown in the UI. Use meta.name.
seedersnumber
leechersnumber
magnetstringFull magnet URI
categorystringTracker-specific category label
publishedAtstringISO 8601
filesArray<{ filename, size }>
source.urlstringTorrent detail page
source.originstringTracker or index name
source.originUrlstringTracker homepage

config

The result of merging minato.defaultConfig with any overrides the admin set in the dashboard. Dashboard values always win; you can't override them from code. Treat config as read-only at runtime.

const { maxPages, delayMs } = config;

signal

Fires on both pause and stop. The scraper can't distinguish between them; that's Minato's concern. Check at loop boundaries and return cleanly when aborted.

for (const page of pages) {
  if (signal.aborted) break;
  // ...
}

Buffered torrents flush automatically before exit. A paused scraper can be resumed on demand; a stopped one waits for its next scheduled run.


status

status.update({
  phase?: "idle" | "running" | "paused" | "error",
  progress?: { current: number; total?: number },
  message?: string,
})

All fields optional. Failed calls are silently ignored.


meta

meta.id       // "my-scraper"
meta.name     // "My Scraper"
meta.version  // "1.0.0"

Use meta.name as source.name in ingest.add() so the source label in the UI stays consistent with the dashboard name.


flaresolverr

A pre-configured FlareSolverr client for sites protected by Cloudflare. Use ffetch as a drop-in replacement for fetch, routing the request through FlareSolverr and returning a standard Response.

import { ffetch } from "@minato/skit";

export default defineScheduledScraper({
  async run(ctx) {
    const res = await ffetch(ctx, "https://protected-site.example/list");
    const html = await res.text();
    // parse and ingest...
  },
});

ffetch supports GET and POST only. It throws if FlareSolverr is unreachable or returns an error, so the failure surfaces as a normal scraper crash rather than silently producing empty results.

On this page