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

# JavaScript SDK

> Complete guide to the official Screenshothis JavaScript SDK

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

<CodeGroup>
  ```bash npm theme={null}
  npm add @screenshothis/sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @screenshothis/sdk
  ```

  ```bash yarn theme={null}
  yarn add @screenshothis/sdk
  ```

  ```bash bun theme={null}
  bun add @screenshothis/sdk
  ```
</CodeGroup>

<Info>
  **TypeScript support**: The SDK includes complete TypeScript definitions out of the box. For optimal support, ensure your `tsconfig.json` targets ES2020 or higher.
</Info>

## Quick start

Get up and running in three simple steps:

<Steps>
  <Step title="Import the SDK">
    ```typescript theme={null}
    import { Screenshothis } from "@screenshothis/sdk";
    ```
  </Step>

  <Step title="Initialize client">
    ```typescript theme={null}
    const screenshothis = new Screenshothis();
    ```
  </Step>

  <Step title="Capture your first screenshot">
    ```typescript theme={null}
    const imageData = await screenshothis.screenshots.take({
      apiKey: "ss_test_1234567890abcdef",
      url: "https://example.com"
    });
    ```
  </Step>
</Steps>

## Basic usage

### Simple screenshot

Capture a basic screenshot with minimal configuration:

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

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

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

<Tip>
  **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.
</Tip>

## Comprehensive error handling

The SDK provides specific error types for different failure scenarios:

### Basic error handling

Handle common errors with try-catch blocks:

```typescript theme={null}
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 Type                  | Status Code | When it occurs                    | How to handle                     |
| --------------------------- | ----------- | --------------------------------- | --------------------------------- |
| `ForbiddenError`            | 403         | API quota exceeded or invalid key | Check your quota and key validity |
| `InternalServerError`       | 500         | Server-side error                 | Retry with exponential backoff    |
| `ScreenshothisDefaultError` | Various     | General API errors                | Check error message for details   |

<Warning>
  Always implement error handling in production applications. Use the `requestId` from error responses when contacting support.
</Warning>

## Advanced configuration

### Custom server URL

Override the default API endpoint for self-hosted instances:

```typescript theme={null}
import { Screenshothis } from "@screenshothis/sdk";

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

### Retry configuration

Configure automatic retries for transient failures:

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

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

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

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

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

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

<AccordionGroup>
  <Accordion title="Performance optimization" icon="rocket">
    * Use tree-shaking imports to reduce bundle size
    * Implement proper caching strategies for screenshots
    * Consider using WebP format for smaller file sizes
    * Batch multiple requests to optimize rate limit usage
    * Use appropriate quality settings based on use case
  </Accordion>

  <Accordion title="Error handling" icon="shield">
    * Always wrap API calls in try-catch blocks
    * Implement retry logic for transient failures
    * Use specific error types for different handling strategies
    * Log request IDs for debugging and support
    * Provide fallback options when screenshots fail
  </Accordion>

  <Accordion title="Security considerations" icon="lock">
    * API keys use domain whitelisting—safe to commit to version control
    * Configure allowed domains in your dashboard to control key usage
    * Validate URLs before sending to the API
    * Implement rate limiting in your own applications
    * Use HTTPS for all API requests in production
  </Accordion>

  <Accordion title="Memory management" icon="cpu">
    * Clean up blob URLs when no longer needed
    * Use streaming for large images when possible
    * Implement proper garbage collection in long-running processes
    * Monitor memory usage in batch processing scenarios
    * Consider using file streams instead of keeping images in memory
  </Accordion>
</AccordionGroup>

## 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

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

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Explore all available API parameters and response formats
  </Card>

  <Card title="Quickstart Guide" icon="rocket" href="/quickstart">
    Get started with basic screenshot capture in minutes
  </Card>

  <Card title="Self-hosting" icon="server" href="/self-host">
    Run Screenshothis on your own infrastructure
  </Card>

  <Card title="GitHub Repository" icon="github" href="https://github.com/screenshothis/screenshothis-js">
    View source code, report issues, or contribute
  </Card>
</CardGroup>
