Screenshot -- Node.js / TypeScript SDK

Official Node.js SDK for the Nodium Screenshot API. Supports Node.js 18+ and all modern runtimes (Deno, Bun).

Installation

bash
npm install @nodium/screenshot
bash
# or with yarn
yarn add @nodium/screenshot

# or with pnpm
pnpm add @nodium/screenshot

Quick Start

typescript
import { NodiumScreenshot } from "@nodium/screenshot";

const client = new NodiumScreenshot("YOUR_API_KEY");

const screenshot = await client.take({
  url: "https://example.com",
  format: "png",
});

// screenshot.data is a Buffer containing the PNG image
fs.writeFileSync("screenshot.png", screenshot.data);

Client Initialization

typescript
import { NodiumScreenshot } from "@nodium/screenshot";

// Basic initialization
const client = new NodiumScreenshot("YOUR_API_KEY");

// With options
const client = new NodiumScreenshot("YOUR_API_KEY", {
  baseUrl: "https://api.nodium.io/api/v1/screenshot",
  timeout: 60_000,        // Request timeout in milliseconds (default: 60000)
  retries: 3,             // Automatic retries on 5xx errors (default: 3)
  retryDelay: 1000,       // Base delay between retries in ms (default: 1000)
});

Environment Variable

You can also set your API key via the NODIUM_API_KEY environment variable:

typescript
// Reads from process.env.NODIUM_API_KEY automatically
const client = new NodiumScreenshot();

Methods

take(params) -- Capture a Screenshot

Takes a screenshot of a URL, HTML, or Markdown content.

typescript
const result = await client.take({
  url: "https://example.com",
  format: "png",
  viewport_width: 1280,
  viewport_height: 1024,
  full_page: true,
  image_quality: 90,
});

// result.data     -- Buffer with image/PDF bytes
// result.headers  -- Response headers (rendering time, size, reference ID)

animate(params) -- Record an Animated Screenshot

Records a scroll animation or interaction video.

typescript
const result = await client.animate({
  url: "https://example.com",
  format: "mp4",
  scroll_animation: "smooth",
  animation_duration: 5,
  viewport_width: 1280,
  viewport_height: 720,
});

fs.writeFileSync("animation.mp4", result.data);

bulk(params) -- Batch Capture

Capture multiple URLs in a single request.

typescript
const results = await client.bulk({
  urls: [
    "https://example.com",
    "https://example.org",
    "https://example.net",
  ],
  format: "png",
  viewport_width: 1280,
  viewport_height: 1024,
});

results.forEach((result, index) => {
  fs.writeFileSync(`screenshot-${index}.png`, result.data);
});

getUsage() -- Check API Usage

Returns your current billing period usage.

typescript
const usage = await client.getUsage();

console.log(`Screenshots taken: ${usage.screenshots_taken}`);
console.log(`Monthly limit: ${usage.monthly_limit}`);
console.log(`Remaining: ${usage.remaining}`);
console.log(`Billing period ends: ${usage.period_end}`);

Fluent Builder API

Every method supports a fluent builder pattern for a more readable configuration style.

typescript
const result = await client
  .take()
  .url("https://example.com")
  .format("png")
  .viewport(1280, 1024)
  .fullPage(true)
  .imageQuality(90)
  .execute();

fs.writeFileSync("screenshot.png", result.data);

Builder Methods

MethodDescription
.url(url)Target URL to capture
.html(html)Raw HTML to render
.markdown(md)Markdown content to render
.format(fmt)Output format: png, jpeg, webp, avif, pdf, etc.
.viewport(width, height)Viewport dimensions
.viewportDevice(device)Device emulation (e.g. iphone_16_pro)
.fullPage(bool)Capture the entire scrollable page
.imageQuality(n)JPEG/WebP quality (1-100)
.selector(css)Capture a specific CSS selector
.delay(ms)Wait before capture (milliseconds)
.blockAds(bool)Block ads and trackers
.darkMode(bool)Force dark color scheme
.responseType(type)by_format, json, or empty
.webhook(url)Webhook URL for async delivery
.execute()Execute the request and return the result

Chaining Example

typescript
const pdf = await client
  .take()
  .url("https://example.com/report")
  .format("pdf")
  .fullPage(true)
  .viewport(1440, 900)
  .delay(2000)
  .blockAds(true)
  .execute();

fs.writeFileSync("report.pdf", pdf.data);

TypeScript Types

The SDK ships with full TypeScript definitions out of the box.

typescript
import {
  NodiumScreenshot,
  ScreenshotParams,
  AnimateParams,
  BulkParams,
  ScreenshotResult,
  UsageResult,
  NodiumError,
  ImageFormat,
  VideoFormat,
  ResponseType,
} from "@nodium/screenshot";

// Typed parameters
const params: ScreenshotParams = {
  url: "https://example.com",
  format: "png",
  viewport_width: 1280,
  viewport_height: 1024,
  full_page: true,
};

// Typed result
const result: ScreenshotResult = await client.take(params);

Key Types

typescript
type ImageFormat = "png" | "jpeg" | "webp" | "avif" | "heif" | "tiff" | "jp2" | "gif";
type VideoFormat = "mp4" | "webm" | "gif" | "mov" | "avi";
type DocumentFormat = "pdf" | "html" | "markdown";
type ResponseType = "by_format" | "json" | "empty";

interface ScreenshotParams {
  url?: string;
  html?: string;
  markdown?: string;
  format: ImageFormat | DocumentFormat;
  viewport_width?: number;
  viewport_height?: number;
  full_page?: boolean;
  image_quality?: number;
  selector?: string;
  delay?: number;
  response_type?: ResponseType;
  webhook_url?: string;
  // ... 145+ additional parameters
}

interface ScreenshotResult {
  data: Buffer;
  headers: {
    renderingSeconds: number;
    sizeBytes: number;
    reference: string;
    traceId: string;
    cacheUrl?: string;
  };
}

Error Handling

The SDK throws typed NodiumError instances for all API errors.

typescript
import { NodiumError } from "@nodium/screenshot";

try {
  const result = await client.take({
    url: "https://example.com",
    format: "png",
  });

  fs.writeFileSync("screenshot.png", result.data);
} catch (error) {
  if (error instanceof NodiumError) {
    console.error(`Error code: ${error.code}`);         // e.g. "request_not_valid"
    console.error(`Message: ${error.message}`);          // Human-readable description
    console.error(`HTTP status: ${error.httpStatus}`);   // e.g. 400
    console.error(`Retryable: ${error.isRetryable}`);    // true for 5xx errors

    if (error.code === "screenshots_limit_reached") {
      console.error("Monthly quota exceeded. Upgrade your plan.");
    }
  } else {
    // Network error, timeout, etc.
    console.error("Unexpected error:", error);
  }
}

Error Codes

CodeHTTP StatusRetryable
access_key_required400No
access_key_invalid400No
request_not_valid400No
screenshots_limit_reached400No
concurrency_limit_reached400No
timeout_error500Yes
network_error500Yes
internal_application_error500Yes
temporary_unavailable503Yes

Webhook Integration

For long-running captures, use webhooks to receive results asynchronously.

typescript
// The API will POST the result to your webhook URL instead of returning it
const result = await client.take({
  url: "https://example.com",
  format: "png",
  webhook_url: "https://your-app.com/api/webhooks/screenshot",
  response_type: "json",
});

// result contains the reference ID immediately
console.log(`Queued: ${result.headers.reference}`);

Express Webhook Handler

typescript
import express from "express";

const app = express();
app.use(express.json());

app.post("/api/webhooks/screenshot", (req, res) => {
  const { screenshot_url, metadata, reference } = req.body;

  console.log(`Screenshot ready: ${screenshot_url}`);
  console.log(`Page title: ${metadata.page_title}`);
  console.log(`Size: ${metadata.image_size.width}x${metadata.image_size.height}`);

  // Download and process the screenshot
  // ...

  res.sendStatus(200);
});

app.listen(3000);

Signed URL Generation

Generate pre-signed URLs that allow third parties to take screenshots without exposing your API key.

typescript
const signedUrl = client.generateSignedUrl({
  url: "https://example.com",
  format: "png",
  viewport_width: 1280,
  viewport_height: 1024,
  expires_in: 3600, // URL valid for 1 hour
});

console.log(signedUrl);
// https://api.nodium.io/api/v1/screenshot/take?url=...&signature=...&expires=...

Use Case: Client-Side Screenshots

typescript
// Server-side: generate a signed URL
app.get("/api/screenshot-url", (req, res) => {
  const signedUrl = client.generateSignedUrl({
    url: req.query.url as string,
    format: "png",
    expires_in: 300,
  });

  res.json({ url: signedUrl });
});

// Client-side: use the signed URL directly in an <img> tag
// <img src="{signedUrl}" alt="Screenshot" />

Advanced Configuration

Custom HTTP Client

Provide a custom fetch implementation for special environments.

typescript
import { NodiumScreenshot } from "@nodium/screenshot";
import { fetch as undiciFetch } from "undici";

const client = new NodiumScreenshot("YOUR_API_KEY", {
  fetch: undiciFetch,
});

Proxy Configuration

Route requests through an HTTP or SOCKS proxy.

typescript
import { ProxyAgent } from "undici";

const proxyAgent = new ProxyAgent("http://proxy.example.com:8080");

const client = new NodiumScreenshot("YOUR_API_KEY", {
  dispatcher: proxyAgent,
});

Timeout Configuration

typescript
const client = new NodiumScreenshot("YOUR_API_KEY", {
  timeout: 120_000,   // 2 minutes for complex pages
  retries: 5,         // More retries for unreliable networks
  retryDelay: 2000,   // 2 second base delay between retries
});

Full Example

A complete example that captures a screenshot, saves it to disk, and handles all error scenarios.

typescript
import { NodiumScreenshot, NodiumError } from "@nodium/screenshot";
import fs from "node:fs";
import path from "node:path";

async function captureAndSave(targetUrl: string, outputPath: string) {
  const client = new NodiumScreenshot(process.env.NODIUM_API_KEY);

  try {
    // Check usage before capturing
    const usage = await client.getUsage();
    if (usage.remaining <= 0) {
      console.error("No screenshots remaining this billing period.");
      process.exit(1);
    }

    console.log(`Remaining quota: ${usage.remaining}/${usage.monthly_limit}`);

    // Take the screenshot using the fluent builder
    const result = await client
      .take()
      .url(targetUrl)
      .format("png")
      .viewport(1440, 900)
      .fullPage(true)
      .blockAds(true)
      .delay(1000)
      .imageQuality(95)
      .execute();

    // Ensure the output directory exists
    fs.mkdirSync(path.dirname(outputPath), { recursive: true });

    // Write the screenshot to disk
    fs.writeFileSync(outputPath, result.data);

    console.log(`Screenshot saved to ${outputPath}`);
    console.log(`Rendering time: ${result.headers.renderingSeconds}s`);
    console.log(`File size: ${(result.headers.sizeBytes / 1024).toFixed(1)} KB`);
    console.log(`Reference: ${result.headers.reference}`);
  } catch (error) {
    if (error instanceof NodiumError) {
      console.error(`API error [${error.code}]: ${error.message}`);

      if (error.isRetryable) {
        console.error("This error is retryable. The SDK already retried automatically.");
      }
    } else {
      console.error("Unexpected error:", error);
    }

    process.exit(1);
  }
}

// Run
captureAndSave("https://example.com", "./output/screenshot.png");

Next Steps