High-quality screenshot utilities for React + Vite apps. Choose native browser APIs (no dependencies, user prompt) or Playwright (automated, headless, full auth state). Perfect for dev tools, debug menus, and capturing UI states.
npm install vite-screenshot-utilHigh-quality screenshot utilities for React + Vite applications. Two approaches to choose from:
- Native Browser APIs (useScreenshot) - No dependencies, prompts user to select tab/window
- Playwright (useScreenshotPlaywright) - Automated headless browser with full auth state (cookies, localStorage, sessionStorage)
Perfect for dev tools, debug menus, automated testing, or capturing UI states.
``bash`
npm install vite-screenshot-util
No additional dependencies needed! html2canvas-pro is bundled for element screenshots.
Install optional peer dependencies:
`bash`
npm install express playwright
Then add the plugin to your vite.config.ts:
`typescript
import { defineConfig } from 'vite';
import { screenshotPlugin } from 'vite-screenshot-util/plugin';
export default defineConfig({
plugins: [
screenshotPlugin({
port: 3001, // Server port (default: 3001)
outputPath: 'screenshots' // Where to save screenshots (default: project root)
})
]
});
`
Uses getDisplayMedia for full page screenshots and html2canvas-pro for element screenshots. No server required, but full-page mode prompts user to select tab/window.
`tsx
import { useScreenshot } from 'vite-screenshot-util';
function MyComponent() {
const { takeScreenshot, isTakingScreenshot } = useScreenshot({
onSuccess: (result) => console.log('Saved:', result.path),
onError: (error) => console.error('Failed:', error.message)
});
return (
{/ Capture by CSS selector /}
Options:
-
element?: HTMLElement | string - Specific element to capture (HTMLElement ref or CSS selector; omit for full page)
- scale?: number - Scale factor for element screenshots (default: 1)$3
Starts a headless browser on-demand, captures with full authentication state, then automatically stops. Requires
screenshotPlugin in your Vite config.`tsx
import { useScreenshotPlaywright } from 'vite-screenshot-util';function MyComponent() {
const { takeScreenshot, isTakingScreenshot } = useScreenshotPlaywright({
onSuccess: (result) => console.log('Saved at:', result.path),
onError: (error) => console.error('Failed:', error.message)
});
return (
{/ Authenticated screenshot with all state copied /}
{/ Unauthenticated screenshot /}
{/ Screenshot different URL with current auth /}
);
}
`Options:
-
element?: HTMLElement | string - Specific element to capture (HTMLElement ref or CSS selector; omit for viewport)
- scale?: number - Device scale factor (default: 2)
- copyCookies?: boolean - Copy cookies to headless browser (default: true)
- copyLocalStorage?: boolean - Copy localStorage to headless browser (default: true)
- copySessionStorage?: boolean - Copy sessionStorage to headless browser (default: true)
- url?: string - Override URL to screenshot (default: current page)API Reference
$3
Both hooks accept these callback options:
`typescript
interface UseScreenshotOptions {
onStart?: () => void; // Called when screenshot begins
onSuccess?: (result: ScreenshotSuccess) => void; // Called on success
onError?: (error: ScreenshotError) => void; // Called on error
onEnd?: (result: ScreenshotResult) => void; // Called on completion (success or error)
}
`$3
`typescript
interface ScreenshotPluginOptions {
port?: number; // Server port (default: 3001)
enabled?: boolean; // Enable/disable plugin (default: true)
outputPath?: string; // Relative path for screenshots (default: project root)
}
`$3
`typescript
interface ScreenshotSuccess {
path: string; // File path or filename
}class ScreenshotError extends Error {
name: 'ScreenshotError';
message: string;
cause?: Error;
}
type ScreenshotResult = ScreenshotSuccess | ScreenshotError;
`How It Works
$3
1. Full Page: Uses
navigator.mediaDevices.getDisplayMedia() to prompt user to select tab/window
2. Element: Uses html2canvas-pro to render element to canvas at specified scale, handling cross-origin content
3. Downloads as PNG file via browser downloadPros:
- Minimal dependencies (html2canvas-pro bundled)
- High quality
- Works everywhere
- Handles cross-origin content in elements
Cons:
- Full page mode prompts user to select tab/window
- Cannot automate full page captures
- Cannot screenshot different URLs
$3
1. Hook calls
/__screenshot_start to start headless browser server
2. Collects current cookies, localStorage, sessionStorage
3. Sends to server with target URL
4. Server launches Playwright, applies auth state, navigates, captures screenshot
5. Saves to disk at configured outputPath
6. Hook calls /__screenshot_stop to shutdown serverPros:
- Fully automated (no user prompt)
- Can screenshot any URL
- Copies full auth state
- Can disable auth copying for testing
Cons:
- Requires Playwright (200MB+ install)
- Requires server setup
- Dev-only (not for production)
Common Use Cases
$3
`tsx
import { useScreenshotPlaywright } from 'vite-screenshot-util';function DebugMenu() {
const { takeScreenshot } = useScreenshotPlaywright({
onSuccess: (result) => {
// Copy path to clipboard
navigator.clipboard.writeText(result.path);
alert(
Screenshot saved: ${result.path});
}
}); return (
);
}
`$3
`tsx
import { useScreenshotPlaywright } from 'vite-screenshot-util';function ComponentTests() {
const { takeScreenshot } = useScreenshotPlaywright();
const captureAllStates = async () => {
// Capture authenticated state
await takeScreenshot({ url: 'http://localhost:3000/dashboard' });
// Capture unauthenticated state
await takeScreenshot({
url: 'http://localhost:3000/login',
copyCookies: false,
copyLocalStorage: false
});
};
return ;
}
`$3
`tsx
import { useScreenshot } from 'vite-screenshot-util';function ChartExport({ chartRef }) {
const { takeScreenshot, isTakingScreenshot } = useScreenshot();
return (
onClick={() => takeScreenshot({ element: chartRef.current, scale: 3 })}
disabled={isTakingScreenshot}
>
Export Chart (3x quality)
);
}
`TypeScript Support
Fully typed with TypeScript. All types are exported:
`typescript
import type {
UseScreenshotOptions,
TakeScreenshotOptions,
TakeScreenshotOptionsPlaywright,
UseScreenshotPlaywrightOptions,
ScreenshotSuccess,
ScreenshotError,
ScreenshotResult,
ScreenshotPluginOptions
} from 'vite-screenshot-util';
``This package uses:
- React 18+ or 19+
- Vite 5+
- TypeScript 5+
- Playwright 1.40+ (optional)
- Express 4+ (optional)
MIT
Adam Kauper
Issues and PRs welcome! This is a public package designed to help developers capture screenshots in React + Vite apps.