ReaderClient
Constructor, options, methods, and lifecycle for the main Reader API.
ReaderClient is the high-level API you'll use for 99% of Reader workloads. It owns the Playwright pool and the browser instances, exposes scrape() and crawl(), and handles lazy initialization.
Constructor
new ReaderClient(options?: ReaderClientOptions)
The constructor does not touch the browser. It only stores configuration. Initialization happens lazily on the first scrape() or crawl() call.
ReaderClientOptions
interface ReaderClientOptions {
verbose?: boolean;
showChrome?: boolean;
browserPool?: BrowserPoolConfig;
proxies?: ProxyConfig[];
proxyPools?: ProxyPoolConfig;
proxyRotation?: "round-robin" | "random";
skipTLSVerification?: boolean;
}
| Option | Type | Default | Description |
|---|---|---|---|
verbose | boolean | false | Enable Pino logging |
showChrome | boolean | false | Show the browser window (debugging) |
browserPool | BrowserPoolConfig | { size: 2 } | Browser pool configuration |
proxies | ProxyConfig[] | - | Flat proxy list for round-robin rotation |
proxyPools | ProxyPoolConfig | - | Multi-tier proxy pools (standard/datacenter, premium/residential) |
proxyRotation | "round-robin" | "random" | "round-robin" | Rotation strategy within a pool |
skipTLSVerification | boolean | true | Skip TLS certificate verification |
See BrowserPoolConfig and ProxyConfig for the nested types.
Methods
async start(): Promise<void>
Pre-warm the client. Initializes the Playwright pool and browser instances without running a scrape. Optional - scrape() and crawl() will initialize automatically if you haven't called start().
async scrape(options: ScrapeOptions): Promise<ScrapeResult>
Scrape one or more URLs. See ScrapeOptions and ScrapeResult.
async crawl(options: CrawlOptions): Promise<CrawlResult>
Discover and optionally scrape pages on a site. See CrawlOptions and CrawlResult.
isReady(): boolean
Returns true if the client has been initialized (via start() or a prior scrape()/crawl() call).
async close(): Promise<void>
Shut down browsers and release resources. Auto-runs on process exit - call explicitly for fast cleanup.
hasProxyTier(tier: "datacenter" | "residential"): boolean
getProxyForTier(tier: "datacenter" | "residential"): ProxyConfig | undefined
Helpers for checking proxy pool availability. Useful when you want to gate behavior on whether a residential pool is configured.
Lifecycle
ReaderClient is lazy by design:
new ReaderClient()- constructor does nothing expensive- First call to
scrape()orcrawl()- triggers Playwright pool startup and browser initialization (1-2 seconds) - Subsequent calls - reuse the warm pool
- Auto cleanup on
SIGTERM/SIGINT/process exit - Explicit
close()- tears down browsers immediately
Reuse a single client instance for the lifetime of your process. Don't create-and-close per request.
Server pattern
import { ReaderClient } from "@vakra-dev/reader";
import express from "express";
const reader = new ReaderClient({
browserPool: { size: 5 },
});
const app = express();
app.use(express.json());
app.post("/scrape", async (req, res) => {
try {
const result = await reader.scrape({
urls: [req.body.url],
formats: ["markdown"],
});
res.json(result);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
process.on("SIGTERM", async () => {
await reader.close();
process.exit(0);
});
app.listen(3001);