> ## Documentation Index
> Fetch the complete documentation index at: https://reader.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# ReaderClient

> Constructor, options, methods, and lifecycle for the main Reader API.

`ReaderClient` is the high-level API you'll use for 99% of self-hosted Reader workloads. It owns the Playwright pool and the browser instances, exposes `scrape()` and `crawl()`, and handles lazy initialization.

## Constructor

```typescript theme={null}
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

```typescript theme={null}
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](https://reader.mintlify.site/self-hosted/concepts/browser-pool.md) and [ProxyConfig](https://reader.mintlify.site/self-hosted/concepts/proxy-tiers.md) for the nested types.

## Methods

```typescript theme={null}
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()`.

```typescript theme={null}
async scrape(options: ScrapeOptions): Promise<ScrapeResult>
```

Scrape one or more URLs. See [ScrapeOptions](https://reader.mintlify.site/self-hosted/api-reference/scrape-options.md) and [ScrapeResult](https://reader.mintlify.site/self-hosted/api-reference/scrape-result.md).

```typescript theme={null}
async crawl(options: CrawlOptions): Promise<CrawlResult>
```

Discover and optionally scrape pages on a site. See [CrawlOptions](https://reader.mintlify.site/self-hosted/api-reference/crawl-options.md) and [CrawlResult](https://reader.mintlify.site/self-hosted/api-reference/crawl-result.md).

```typescript theme={null}
isReady(): boolean
```

Returns `true` if the client has been initialized (via `start()` or a prior `scrape()`/`crawl()` call).

```typescript theme={null}
async close(): Promise<void>
```

Shut down browsers and release resources. Auto-runs on process exit - call explicitly for fast cleanup.

```typescript theme={null}
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:

1. `new ReaderClient()` - constructor does nothing expensive
2. First call to `scrape()` or `crawl()` - triggers Playwright pool startup and browser initialization (1-2 seconds)
3. Subsequent calls - reuse the warm pool
4. Auto cleanup on `SIGTERM`/`SIGINT`/process exit
5. 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

```javascript theme={null}
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);
```

## Where to go next

> [card] [scrape()](https://reader.mintlify.site/self-hosted/api-reference/scrape.md)
>
> Signature, options, and return type.

> [card] [crawl()](https://reader.mintlify.site/self-hosted/api-reference/crawl.md)
>
> Signature, options, and return type.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.