Use the official Screenshothis SDK for JavaScript and TypeScript applications to capture screenshots with full type safety and IDE support. The SDK provides a clean interface, comprehensive error handling, and optimized bundle sizes through tree-shaking.

Installation

npm add @screenshothis/sdk
TypeScript support: The SDK includes complete TypeScript definitions out of the box. For optimal support, ensure your tsconfig.json targets ES2020 or higher.

Quick start

Get up and running in three simple steps:
1

Import the SDK

import { Screenshothis } from "@screenshothis/sdk";
2

Initialize client

const screenshothis = new Screenshothis();
3

Capture your first screenshot

const imageData = await screenshothis.screenshots.take({
  apiKey: "ss_test_1234567890abcdef",
  url: "https://example.com"
});

Basic usage

Simple screenshot

Capture a basic screenshot with minimal configuration:
import { Screenshothis } from "@screenshothis/sdk";

const screenshothis = new Screenshothis();

async function takeScreenshot() {
  try {
    const imageData = await screenshothis.screenshots.take({
      apiKey: "ss_test_1234567890abcdef",
      url: "https://github.com"
    });

    // Save to file (Node.js)
    const fs = require('fs');
    fs.writeFileSync('screenshot.jpeg', Buffer.from(imageData));
    console.log('Screenshot saved successfully!');

    // Or display in browser
    const blob = new Blob([imageData], { type: 'image/jpeg' });
    const imageUrl = URL.createObjectURL(blob);
    document.getElementById('screenshot').src = imageUrl;
  } catch (error) {
    console.error('Screenshot failed:', error.message);
  }
}

takeScreenshot();

Advanced screenshot with options

Configure your screenshot with full control over the output:
import type { GetV1ScreenshotsTakeRequest } from "@screenshothis/sdk/models/operations";

async function takeAdvancedScreenshot() {
  try {
    const result = await screenshothis.screenshots.take({
      apiKey: "ss_test_1234567890abcdef",
      url: "https://github.com",

      // Image settings
      format: "png",
      quality: 90,
      width: 1920,
      height: 1080,

      // Content blocking
      blockAds: true,
      blockCookieBanners: true,
      blockTrackers: true,
      blockResources: ["script", "image"],

      // Browser preferences
      prefersColorScheme: "dark",
      prefersReducedMotion: "reduce",

      // Device simulation
      isMobile: false,
      isLandscape: true,
      hasTouch: false,
      deviceScaleFactor: 2,

      // Advanced options
      selector: "#main-content",
      userAgent: "MyApp/1.0",
      bypassCsp: true
    });

    // Process the screenshot
    const fs = require('fs');
    fs.writeFileSync('advanced-screenshot.png', Buffer.from(result));
    console.log('Advanced screenshot saved!');
  } catch (error) {
    console.error('Failed to capture screenshot:', error.message);
  }
}

Tree-shaking optimization

Reduce your bundle size by up to 80% using tree-shakable standalone functions:
import { ScreenshothisCore } from "@screenshothis/sdk/core.js";
import { screenshotsTake } from "@screenshothis/sdk/funcs/screenshotsTake.js";

// Create one instance to use across your application
const screenshothis = new ScreenshothisCore();

async function takeOptimizedScreenshot() {
  const res = await screenshotsTake(screenshothis, {
    apiKey: "ss_test_1234567890abcdef",
    url: "https://example.com",
    format: "webp",
    quality: 85
  });

  if (res.ok) {
    // Success - save the image
    const fs = require('fs');
    fs.writeFileSync('screenshot.webp', Buffer.from(res.value));
    console.log('Optimized screenshot saved!');
  } else {
    // Handle error
    console.error("Screenshot failed:", res.error);
  }
}
Bundle size benefit: Tree-shaking can reduce your bundle size by up to 80% compared to the full SDK import, making it perfect for client-side applications.

Comprehensive error handling

The SDK provides specific error types for different failure scenarios:

Basic error handling

Handle common errors with try-catch blocks:
import { Screenshothis } from "@screenshothis/sdk";
import * as errors from "@screenshothis/sdk/models/errors";

const screenshothis = new Screenshothis();

async function captureWithErrorHandling() {
  try {
    const imageData = await screenshothis.screenshots.take({
      apiKey: "ss_test_1234567890abcdef",
      url: "https://example.com"
    });

    // Save successful screenshot
    const fs = require('fs');
    fs.writeFileSync('screenshot.jpeg', Buffer.from(imageData));
    console.log('Screenshot saved successfully!');

  } catch (error) {
    if (error instanceof errors.ScreenshothisError) {
      console.error('API Error:', error.message);
      console.error('Status code:', error.statusCode);
      console.error('Response body:', error.body);
      console.error('Response headers:', error.headers);

      // Handle specific error types
      if (error instanceof errors.ForbiddenError) {
        console.error('Quota exceeded:', error.data$.error);
        console.error('Request ID:', error.data$.requestId);
        // Maybe show upgrade prompt to user
      }
    } else {
      console.error('Unexpected error:', error);
    }
  }
}

Error types reference

Error TypeStatus CodeWhen it occursHow to handle
ForbiddenError403API quota exceeded or invalid keyCheck your quota and key validity
InternalServerError500Server-side errorRetry with exponential backoff
ScreenshothisDefaultErrorVariousGeneral API errorsCheck error message for details
Always implement error handling in production applications. Use the requestId from error responses when contacting support.

Advanced configuration

Custom server URL

Override the default API endpoint for self-hosted instances:
import { Screenshothis } from "@screenshothis/sdk";

const screenshothis = new Screenshothis({
  serverURL: "https://your-instance.example.com"
});

Retry configuration

Configure automatic retries for transient failures:
import { Screenshothis } from "@screenshothis/sdk";

// Global retry configuration
const screenshothis = new Screenshothis({
  retryConfig: {
    strategy: "backoff",
    backoff: {
      initialInterval: 1000,
      maxInterval: 60000,
      exponent: 1.5,
      maxElapsedTime: 300000
    },
    retryConnectionErrors: true
  }
});

// Per-request retry configuration
async function takeScreenshotWithCustomRetry() {
  const result = await screenshothis.screenshots.take({
    apiKey: "ss_test_1234567890abcdef",
    url: "https://example.com"
  }, {
    retries: {
      strategy: "backoff",
      backoff: {
        initialInterval: 500,
        maxInterval: 10000,
        exponent: 2,
        maxElapsedTime: 30000
      },
      retryConnectionErrors: false
    }
  });
}

Custom HTTP client

Add request hooks and custom behavior:
import { Screenshothis } from "@screenshothis/sdk";
import { HTTPClient } from "@screenshothis/sdk/lib/http";

const httpClient = new HTTPClient({
  fetcher: (request) => {
    return fetch(request);
  }
});

// Add request hooks
httpClient.addHook("beforeRequest", (request) => {
  const nextRequest = new Request(request, {
    signal: request.signal || AbortSignal.timeout(5000)
  });

  nextRequest.headers.set("x-custom-header", "MyApp/1.0");
  return nextRequest;
});

httpClient.addHook("requestError", (error, request) => {
  console.group("Request Error");
  console.log("Reason:", `${error}`);
  console.log("Endpoint:", `${request.method} ${request.url}`);
  console.groupEnd();
});

const sdk = new Screenshothis({ httpClient });

Real-world examples

React component for screenshot capture

Create a reusable React component for screenshot functionality:
import React, { useState, useEffect } from 'react';
import { Screenshothis } from "@screenshothis/sdk";
import type { GetV1ScreenshotsTakeRequest } from "@screenshothis/sdk/models/operations";

type ScreenshotOptions = Omit<GetV1ScreenshotsTakeRequest, "apiKey" | "url">;

interface ScreenshotCapturerProps {
  url: string;
  apiKey: string;
  options?: ScreenshotOptions;
  onSuccess?: (imageUrl: string) => void;
  onError?: (error: string) => void;
}

const ScreenshotCapturer: React.FC<ScreenshotCapturerProps> = ({
  url,
  apiKey,
  options,
  onSuccess,
  onError
}) => {
  const [screenshotUrl, setScreenshotUrl] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const captureScreenshot = async () => {
    setLoading(true);
    setError(null);

    try {
      const screenshothis = new Screenshothis();
      const imageData = await screenshothis.screenshots.take({
        apiKey,
        url,
        format: "webp",
        quality: 85,
        ...options
      });

      const blob = new Blob([imageData], { type: 'image/webp' });
      const blobUrl = URL.createObjectURL(blob);
      setScreenshotUrl(blobUrl);
      onSuccess?.(blobUrl);
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Screenshot failed';
      setError(errorMessage);
      onError?.(errorMessage);
    } finally {
      setLoading(false);
    }
  };

  // Cleanup blob URL when component unmounts
  useEffect(() => {
    return () => {
      if (screenshotUrl) {
        URL.revokeObjectURL(screenshotUrl);
      }
    };
  }, [screenshotUrl]);

  return (
    <div className="screenshot-capturer">
      <button
        onClick={captureScreenshot}
        disabled={loading}
        className="btn btn-primary"
      >
        {loading ? 'Capturing...' : 'Take Screenshot'}
      </button>

      {error && (
        <div className="error">
          <p style={{ color: 'red' }}>Error: {error}</p>
        </div>
      )}

      {screenshotUrl && (
        <div className="screenshot-result">
          <img
            src={screenshotUrl}
            alt="Screenshot"
            style={{ maxWidth: '100%', marginTop: '1rem' }}
          />
        </div>
      )}
    </div>
  );
};

export default ScreenshotCapturer;

Node.js batch processing

Process multiple URLs efficiently with concurrency control:
import { Screenshothis } from "@screenshothis/sdk";
import * as fs from 'fs';
import * as path from 'path';

class ScreenshotBatcher {
  private screenshothis: Screenshothis;

  constructor(private apiKey: string) {
    this.screenshothis = new Screenshothis({
      retryConfig: {
        strategy: "backoff",
        backoff: {
          initialInterval: 1000,
          maxInterval: 30000,
          exponent: 2,
          maxElapsedTime: 120000
        },
        retryConnectionErrors: true
      }
    });
  }

  async processUrls(urls: string[], outputDir: string, concurrency: number = 3) {
    // Ensure output directory exists
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir, { recursive: true });
    }

    // Process URLs in batches to respect rate limits
    const results: Array<PromiseSettledResult<any>> = [];

    for (let i = 0; i < urls.length; i += concurrency) {
      const batch = urls.slice(i, i + concurrency);
      const batchPromises = batch.map((url, index) =>
        this.captureScreenshot(url, outputDir, i + index + 1)
      );

      const batchResults = await Promise.allSettled(batchPromises);
      results.push(...batchResults);

      // Add delay between batches to respect rate limits
      if (i + concurrency < urls.length) {
        await new Promise(resolve => setTimeout(resolve, 1000));
      }
    }

    const successful = results.filter(r => r.status === 'fulfilled').length;
    const failed = results.filter(r => r.status === 'rejected').length;

    console.log(`Batch complete: ${successful} successful, ${failed} failed`);
    return results;
  }

  private async captureScreenshot(url: string, outputDir: string, index: number) {
    try {
      const imageData = await this.screenshothis.screenshots.take({
        apiKey: this.apiKey,
        url,
        format: "png",
        quality: 90,
        width: 1920,
        height: 1080,
        blockAds: true,
        prefersColorScheme: "light"
      });

      const filename = `screenshot-${index.toString().padStart(3, '0')}.png`;
      const filepath = path.join(outputDir, filename);

      fs.writeFileSync(filepath, Buffer.from(imageData));
      console.log(`✅ Saved: ${filename} for ${url}`);

      return { url, filepath, success: true };
    } catch (error) {
      console.error(`❌ Failed: ${url} - ${error.message}`);
      throw error;
    }
  }
}

// Usage example
async function runBatchProcess() {
  const batcher = new ScreenshotBatcher("ss_test_1234567890abcdef");
  const urls = [
    "https://github.com",
    "https://example.com",
    "https://google.com",
    "https://stackoverflow.com"
  ];

  await batcher.processUrls(urls, "./screenshots", 2);
}

runBatchProcess().catch(console.error);

Express.js API integration

Build a screenshot service with Express.js:
import express from 'express';
import { Screenshothis } from "@screenshothis/sdk";
import * as errors from "@screenshothis/sdk/models/errors";

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

const screenshothis = new Screenshothis();

app.post('/api/screenshot', async (req, res) => {
  try {
    const { url, apiKey, ...options } = req.body;

    // Validate required fields
    if (!url || !apiKey) {
      return res.status(400).json({
        error: 'Missing required fields: url and apiKey'
      });
    }

    // Validate URL format
    try {
      new URL(url);
    } catch {
      return res.status(400).json({
        error: 'Invalid URL format'
      });
    }

    const imageData = await screenshothis.screenshots.take({
      apiKey,
      url,
      format: 'webp',
      quality: 85,
      ...options
    });

    // Set appropriate headers
    res.set({
      'Content-Type': 'image/webp',
      'Content-Length': imageData.length.toString(),
      'Cache-Control': 'public, max-age=3600',
      'Access-Control-Allow-Origin': '*'
    });

    res.send(Buffer.from(imageData));

  } catch (error) {
    console.error('Screenshot API error:', error);

    if (error instanceof errors.ForbiddenError) {
      res.status(403).json({
        error: 'API quota exceeded or invalid key',
        requestId: error.data$.requestId
      });
    } else if (error instanceof errors.ScreenshothisError) {
      res.status(error.statusCode || 500).json({
        error: error.message,
        statusCode: error.statusCode
      });
    } else {
      res.status(500).json({
        error: 'Internal server error'
      });
    }
  }
});

// Health check endpoint
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Screenshot API server running on port ${PORT}`);
});

Vue.js composable

Create a Vue composable for screenshot functionality:
import { ref, onUnmounted } from 'vue';
import { Screenshothis } from "@screenshothis/sdk";
import type { GetV1ScreenshotsTakeRequest } from "@screenshothis/sdk/models/operations";

type ScreenshotOptions = Omit<GetV1ScreenshotsTakeRequest, "apiKey" | "url">;

export function useScreenshot(apiKey: string) {
  const screenshotUrl = ref<string | null>(null);
  const loading = ref(false);
  const error = ref<string | null>(null);

  const screenshothis = new Screenshothis();

  const captureScreenshot = async (url: string, options?: ScreenshotOptions) => {
    loading.value = true;
    error.value = null;

    try {
      const imageData = await screenshothis.screenshots.take({
        apiKey,
        url,
        format: "webp",
        quality: 85,
        ...options
      });

      // Clean up previous URL
      if (screenshotUrl.value) {
        URL.revokeObjectURL(screenshotUrl.value);
      }

      const blob = new Blob([imageData], { type: 'image/webp' });
      screenshotUrl.value = URL.createObjectURL(blob);

    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Screenshot failed';
    } finally {
      loading.value = false;
    }
  };

  // Cleanup on unmount
  onUnmounted(() => {
    if (screenshotUrl.value) {
      URL.revokeObjectURL(screenshotUrl.value);
    }
  });

  return {
    screenshotUrl,
    loading,
    error,
    captureScreenshot
  };
}

Best practices

TypeScript support

The SDK provides comprehensive TypeScript support with:
  • Full type definitions for all API parameters and responses
  • IntelliSense support in VS Code and other editors
  • Compile-time validation for API parameters
  • Type-safe error handling with specific error classes
  • Generic types for custom configurations
import type {
  GetV1ScreenshotsTakeRequest,
  ScreenshothisError,
  ForbiddenError
} from "@screenshothis/sdk/models";

// All parameters are fully typed
const params: GetV1ScreenshotsTakeRequest = {
  apiKey: "ss_test_1234567890abcdef",
  url: "https://example.com",
  format: "png", // TypeScript will validate this
  quality: 90,   // TypeScript knows this should be a number
  width: 1920
};

Next steps