SnapAPI/sdk/node/README.md
SnapAPI Developer 9290c759da
Some checks failed
Build & Deploy to Staging / Build & Deploy to Staging (push) Has been cancelled
feat: add userAgent parameter for custom User-Agent headers
- Add userAgent?: string to ScreenshotOptions interface
- Implement validation (max 500 chars, no newlines for security)
- Call page.setUserAgent() after page acquisition, before navigation
- Add route handler support for both POST body and GET query
- Add comprehensive test coverage (11 new tests)
- Update OpenAPI documentation with parameter specs and examples
- Update Node.js and Python SDK README examples
- All userAgent tests passing (414 → 425 total tests)

Fixes potential HTTP header injection by rejecting newlines.
Enables custom User-Agent strings for specific browser emulation needs.
2026-03-05 15:10:06 +01:00

220 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SnapAPI Node.js SDK
Official Node.js client for [SnapAPI](https://snapapi.eu) — the EU-hosted screenshot API.
## Installation
```bash
npm install snapapi
```
## Quick Start
```typescript
import { SnapAPI } from 'snapapi';
import fs from 'fs';
const snap = new SnapAPI('your-api-key');
// Simple screenshot
const png = await snap.capture('https://example.com');
fs.writeFileSync('screenshot.png', png);
```
## Usage
### Basic Screenshot
```typescript
const screenshot = await snap.capture('https://example.com');
```
### With Options
```typescript
const screenshot = await snap.capture('https://example.com', {
format: 'jpeg',
width: 1920,
height: 1080,
quality: 90,
});
```
### Full-Page Capture
```typescript
const screenshot = await snap.capture({
url: 'https://example.com/blog',
fullPage: true,
format: 'png',
deviceScale: 2, // Retina
});
```
### Mobile Viewport
```typescript
const screenshot = await snap.capture({
url: 'https://example.com',
width: 375,
height: 812,
deviceScale: 2,
});
```
### Wait for Dynamic Content
```typescript
const screenshot = await snap.capture({
url: 'https://example.com/dashboard',
waitForSelector: '#chart-loaded',
waitUntil: 'networkidle2',
});
```
### Dark Mode Capture
```typescript
// Capture in dark mode (prefers-color-scheme: dark)
const darkScreenshot = await snap.capture({
url: 'https://example.com',
darkMode: true,
format: 'png',
});
```
### Custom User Agent
```typescript
// Set a custom User-Agent string for the request
const screenshot = await snap.capture({
url: 'https://example.com',
userAgent: 'Mozilla/5.0 (compatible; SnapAPI/1.0)',
format: 'png',
});
```
### Hide Elements Before Capture
```typescript
// Hide cookie banners, popups, ads
const cleanScreenshot = await snap.capture({
url: 'https://example.com',
hideSelectors: [
'.cookie-banner',
'.popup-overlay',
'#advertisement',
'.tracking-notice'
],
});
// Hide single element
const singleHide = await snap.capture('https://example.com', {
hideSelectors: '.newsletter-popup',
});
```
### Custom CSS Injection
```typescript
// Inject custom CSS before capture
const styled = await snap.capture({
url: 'https://example.com',
css: 'body { background: #1a1a2e !important; color: #eee !important; font-family: "Comic Sans MS" }',
});
// Combine with other options
const combined = await snap.capture({
url: 'https://example.com',
css: '.hero { padding: 80px 0 } h1 { font-size: 48px }',
darkMode: true,
hideSelectors: ['.cookie-banner'],
});
```
### JavaScript Injection
```typescript
// Execute custom JavaScript before capture
const interactiveScreenshot = await snap.capture({
url: 'https://example.com',
js: `
// Dismiss modal popup
document.querySelector('.modal-overlay')?.remove();
// Scroll to specific content
window.scrollTo(0, 500);
// Click button to reveal content
document.querySelector('#show-more-btn')?.click();
// Wait for animation to complete
await new Promise(resolve => setTimeout(resolve, 1000));
`,
});
// Combine with other options for complex scenarios
const complexCapture = await snap.capture({
url: 'https://example.com/app',
js: 'document.querySelector(".sidebar").style.display = "none";',
css: 'body { zoom: 0.8 }',
waitForSelector: '#content-loaded',
hideSelectors: ['.ad-banner', '.cookie-notice'],
});
```
## API Reference
### `new SnapAPI(apiKey, config?)`
| Parameter | Type | Description |
|-----------|------|-------------|
| `apiKey` | `string` | Your SnapAPI API key (required) |
| `config.baseUrl` | `string` | API base URL (default: `https://snapapi.eu`) |
| `config.timeout` | `number` | Request timeout in ms (default: `30000`) |
### `snap.capture(url, options?)` / `snap.capture(options)`
Returns a `Promise<Buffer>` containing the screenshot image.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `url` | `string` | — | URL to capture (required) |
| `format` | `'png' \| 'jpeg' \| 'webp'` | `'png'` | Output format |
| `width` | `number` | `1280` | Viewport width (3203840) |
| `height` | `number` | `800` | Viewport height (2002160) |
| `fullPage` | `boolean` | `false` | Capture full scrollable page |
| `quality` | `number` | `80` | JPEG/WebP quality (1100) |
| `waitForSelector` | `string` | — | CSS selector to wait for |
| `deviceScale` | `number` | `1` | Device pixel ratio (13) |
| `delay` | `number` | `0` | Extra delay in ms (05000) |
| `waitUntil` | `string` | `'domcontentloaded'` | Load event to wait for |
| `darkMode` | `boolean` | `false` | Emulate prefers-color-scheme: dark |
| `hideSelectors` | `string \| string[]` | — | CSS selectors to hide before capture |
| `css` | `string` | — | Custom CSS to inject before capture (max 5000 chars) |
### `snap.health()`
Returns API health status.
### Error Handling
```typescript
import { SnapAPI, SnapAPIError } from 'snapapi';
try {
const screenshot = await snap.capture('https://example.com');
} catch (err) {
if (err instanceof SnapAPIError) {
console.error(`API error ${err.status}: ${err.detail}`);
}
}
```
## EU-Hosted & GDPR Compliant
SnapAPI runs entirely on EU infrastructure (Germany). Your data never leaves the EU. [Learn more](https://snapapi.eu).
## License
MIT — [Cloonar Technologies GmbH](https://snapapi.eu)