Official Node.js SDK for len.sh — Screenshot, OG Image & PDF generation API.
npm install lenshimport LenSh from "lensh";
const lensh = new LenSh("sk_live_your_api_key");
// Take a screenshot
const screenshot = await lensh.screenshot("https://example.com");
// screenshot.data is an ArrayBuffer — write it to a file:
import { writeFile } from "node:fs/promises";
await writeFile("screenshot.png", Buffer.from(screenshot.data));
// Generate a PDF
const pdf = await lensh.pdf("https://example.com");
await writeFile("page.pdf", Buffer.from(pdf.data));
// Generate an OG image
const og = await lensh.ogImage({
title: "Hello World",
subtitle: "Generated with len.sh",
theme: "dark",
});
await writeFile("og.png", Buffer.from(og.data));const lensh = new LenSh(apiKey: string, options?: {
baseUrl?: string; // default: "https://api.len.sh"
});Take a screenshot of a URL.
const result = await lensh.screenshot("https://example.com", {
width: 1920,
height: 1080,
format: "webp",
quality: 90,
full_page: true,
block_ads: true,
block_cookie_banners: true,
delay: 1000,
});Options:
| Option | Type | Default | Description |
|---|---|---|---|
width |
number |
1280 |
Viewport width (1-3840) |
height |
number |
720 |
Viewport height (1-2160) |
device |
string |
— | Device preset (e.g. "iphone-14") |
device_scale |
number |
1 |
Device pixel ratio (1-3) |
format |
"png" | "jpeg" | "webp" |
"png" |
Image format |
quality |
number |
80 |
Image quality (1-100) |
full_page |
boolean |
false |
Capture full scrollable page |
wait_until |
string |
"load" |
"load", "domcontentloaded", "networkidle0", "networkidle2" |
timeout |
number |
15000 |
Render timeout in ms (1-30000) |
delay |
number |
0 |
Delay after load in ms (0-10000) |
selector |
string |
— | CSS selector to capture |
transparent |
boolean |
false |
Transparent background |
block_ads |
boolean |
false |
Block ad requests |
block_cookie_banners |
boolean |
false |
Block cookie banners |
block_popups |
boolean |
false |
Block popups |
js |
string |
— | Inject custom JavaScript |
css |
string |
— | Inject custom CSS |
user_agent |
string |
— | Custom user agent |
cache_ttl |
number |
86400 |
Cache TTL in seconds (0 = disable) |
response_type |
"image" | "json" |
"image" |
Return binary or JSON metadata |
Returns ScreenshotImageResult (or ScreenshotJsonResult when response_type: "json"):
// Image result
{ data: ArrayBuffer, contentType: string, cache: "HIT" | "MISS", renderTime: number, requestId: string }
// JSON result
{ url: string, width: number, height: number, format: string, size: number, cache: string, render_time_ms: number, request_id: string }Take a screenshot of raw HTML content.
const result = await lensh.screenshotHtml("<h1>Hello World</h1>", {
width: 800,
height: 600,
});Generate an Open Graph image.
const result = await lensh.ogImage({
title: "My Blog Post",
subtitle: "A deep dive into Node.js SDKs",
badge: "NEW",
url: "https://myblog.com/post",
brand_name: "My Blog",
brand_color: "#ff6600",
theme: "light",
format: "png",
quality: 90,
});Options:
| Option | Type | Default | Description |
|---|---|---|---|
title |
string |
required | Main title (1-200 chars) |
subtitle |
string |
— | Subtitle (1-300 chars) |
badge |
string |
— | Badge text (1-50 chars) |
url |
string |
— | Display URL on image |
brand_name |
string |
— | Brand name (1-100 chars) |
brand_color |
string |
"#4850e5" |
Brand color (hex) |
theme |
"dark" | "light" |
"dark" |
Color theme |
format |
"png" | "jpeg" | "webp" |
"png" |
Image format |
quality |
number |
90 |
Image quality (1-100) |
cache_ttl |
number |
86400 |
Cache TTL in seconds |
Generate a PDF from a URL.
const result = await lensh.pdf("https://example.com", {
paper_size: "Letter",
landscape: true,
print_background: true,
margin_top: "1in",
margin_bottom: "1in",
});Options:
| Option | Type | Default | Description |
|---|---|---|---|
paper_size |
string |
"A4" |
"A4", "Letter", "Legal", "Tabloid", "Ledger" |
landscape |
boolean |
false |
Landscape orientation |
scale |
number |
1.0 |
Scale factor (0.1-2.0) |
margin_top |
string |
"0.4in" |
Top margin (CSS value) |
margin_right |
string |
"0.4in" |
Right margin |
margin_bottom |
string |
"0.4in" |
Bottom margin |
margin_left |
string |
"0.4in" |
Left margin |
print_background |
boolean |
true |
Include backgrounds |
page_ranges |
string |
— | Pages to include (e.g. "1-3") |
header_template |
string |
— | HTML header template |
footer_template |
string |
— | HTML footer template |
wait_until |
string |
"load" |
Wait strategy |
timeout |
number |
15000 |
Render timeout in ms |
delay |
number |
0 |
Delay after load in ms |
block_ads |
boolean |
false |
Block ad requests |
block_cookie_banners |
boolean |
false |
Block cookie banners |
js |
string |
— | Inject custom JavaScript |
css |
string |
— | Inject custom CSS |
cache_ttl |
number |
86400 |
Cache TTL in seconds |
response_type |
"pdf" | "json" |
"pdf" |
Return binary or JSON metadata |
Generate a PDF from raw HTML content.
const result = await lensh.pdfFromHtml("<h1>Invoice #123</h1><p>Total: $99</p>", {
paper_size: "A4",
margin_top: "1in",
});import LenSh, { LenShApiError } from "lensh";
try {
await lensh.screenshot("https://example.com");
} catch (err) {
if (err instanceof LenShApiError) {
console.error(err.code); // "RATE_LIMITED", "QUOTA_EXCEEDED", etc.
console.error(err.statusCode); // 429
console.error(err.message); // Human-readable message
console.error(err.requestId); // Request ID for support
}
}Error codes: MISSING_URL, INVALID_URL, INVALID_PARAMETER, UNAUTHORIZED, RATE_LIMITED, QUOTA_EXCEEDED, RENDER_FAILED, RENDER_TIMEOUT, INTERNAL_ERROR
- Node.js 18+ (uses native
fetch) - No external dependencies
MIT