Skip to main content
Glama
ananddtyagi

Webpage Screenshot MCP Server

screenshot-page

Capture screenshots of any webpage as base64 encoded images with customizable settings like viewport size, image format, and loading conditions. Supports using saved cookies for authenticated pages.

Instructions

Captures a screenshot of a given URL and returns it as base64 encoded image. Can use saved cookies from login-and-wait.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
delayNoAdditional delay in milliseconds to wait after page load
formatNoImage format for the screenshotpng
fullPageNoWhether to capture the full page or just the viewport
heightNoViewport height in pixels
qualityNoQuality of the image (0-100), only applicable for jpeg and webp
reuseAuthPageNoWhether to use the existing authenticated page instead of creating a new one
urlYesThe URL of the webpage to screenshot
useDefaultBrowserNoWhether to use the system's default browser instead of Puppeteer's bundled Chromium
useSavedAuthNoWhether to use saved cookies from previous login
visibleBrowserNoWhether to show the browser window (non-headless mode)
waitForNoWhen to consider the page loadednetworkidle2
widthNoViewport width in pixels

Implementation Reference

  • The handler function that implements the core logic for capturing screenshots of web pages using Puppeteer. Supports authentication via saved cookies, full-page screenshots, custom dimensions, formats, delays, browser visibility, and default system browser usage.
    async ({ url, fullPage, width, height, format, quality, waitFor, delay, useSavedAuth, reuseAuthPage, useDefaultBrowser, visibleBrowser }) => { let page: Page | null = null; let shouldClosePage = true; try { // Initialize browser with appropriate options const isHeadless = !visibleBrowser; const browserInstance = await initBrowser(isHeadless, useDefaultBrowser && visibleBrowser); // Check if we should reuse the authenticated page if (reuseAuthPage && persistentPage && !persistentPage.isClosed()) { page = persistentPage; shouldClosePage = false; // Navigate to the new URL if different const currentUrl = page.url(); if (currentUrl !== url) { await page.goto(url, { waitUntil: waitFor as any, timeout: 30000 }); } } else { // Create a new page page = await browserInstance.newPage(); // Load saved cookies if requested if (useSavedAuth) { const cookies = await loadCookies(url); if (cookies.length > 0) { await page.setCookie(...cookies); } } // Set viewport await page.setViewport({ width, height }); // Set user agent to avoid bot detection await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); // Additional anti-detection measures for Google await page.evaluateOnNewDocument(() => { // Remove webdriver property delete (window.navigator as any).webdriver; // Override the plugins property to add fake plugins Object.defineProperty(window.navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] }); // Override the languages property Object.defineProperty(window.navigator, 'languages', { get: () => ['en-US', 'en'] }); // Override permissions Object.defineProperty(window.navigator, 'permissions', { get: () => ({ query: () => Promise.resolve({ state: 'granted' }) }) }); }); // Navigate to the URL await page.goto(url, { waitUntil: waitFor as any, timeout: 30000 }); } // Optional delay if (delay > 0) { await new Promise(resolve => setTimeout(resolve, delay)); } // Prepare screenshot options const screenshotOptions: any = { encoding: 'base64', fullPage, type: format }; // Add quality option for jpeg and webp if ((format === 'jpeg' || format === 'webp') && quality !== undefined) { screenshotOptions.quality = quality; } // Take screenshot const screenshot = await page.screenshot(screenshotOptions) as string; // Get page title and final URL for context const pageTitle = await page.title(); const finalUrl = page.url(); // If using a new page, save any new cookies if (!reuseAuthPage && useSavedAuth) { const currentCookies = await page.cookies(); if (currentCookies.length > 0) { await saveCookies(url, currentCookies); } } // Determine browser type for response const browserType = useDefaultBrowser && visibleBrowser ? 'default browser' : 'Puppeteer browser'; const browserMode = visibleBrowser ? 'visible' : 'headless'; return { content: [ { type: "text", text: `Screenshot captured successfully!\n\nBrowser: ${browserType} (${browserMode})\nPage Title: ${pageTitle}\nFinal URL: ${finalUrl}\nFormat: ${format}\nDimensions: ${width}x${height}\nFull Page: ${fullPage}\nUsed saved auth: ${useSavedAuth}\nReused auth page: ${reuseAuthPage}` }, { type: "image", data: screenshot, mimeType: `image/${format}` } ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { isError: true, content: [ { type: "text", text: `Error capturing screenshot: ${errorMessage}`, }, ], }; } finally { // Only close the page if it's not the persistent one or if we should close it if (page && shouldClosePage && page !== persistentPage) { await page.close().catch(() => {}); } } }
  • Zod schema defining the input parameters for the screenshot-page tool, including URL, screenshot options, authentication flags, and browser configuration.
    { url: z.string().url().describe("The URL of the webpage to screenshot"), fullPage: z.boolean().optional().default(true).describe("Whether to capture the full page or just the viewport"), width: z.number().optional().default(1920).describe("Viewport width in pixels"), height: z.number().optional().default(1080).describe("Viewport height in pixels"), format: z.enum(['png', 'jpeg', 'webp']).optional().default('png').describe("Image format for the screenshot"), quality: z.number().min(0).max(100).optional().describe("Quality of the image (0-100), only applicable for jpeg and webp"), waitFor: z.enum(['load', 'domcontentloaded', 'networkidle0', 'networkidle2']).optional().default('networkidle2').describe("When to consider the page loaded"), delay: z.number().optional().default(0).describe("Additional delay in milliseconds to wait after page load"), useSavedAuth: z.boolean().optional().default(true).describe("Whether to use saved cookies from previous login"), reuseAuthPage: z.boolean().optional().default(false).describe("Whether to use the existing authenticated page instead of creating a new one"), useDefaultBrowser: z.boolean().optional().default(false).describe("Whether to use the system's default browser instead of Puppeteer's bundled Chromium"), visibleBrowser: z.boolean().optional().default(false).describe("Whether to show the browser window (non-headless mode)") },
  • src/index.ts:496-651 (registration)
    Registration of the screenshot-page tool on the MCP server, including name, description, input schema, and handler function.
    // Updated screenshot-page tool with authentication support server.tool( "screenshot-page", "Captures a screenshot of a given URL and returns it as base64 encoded image. Can use saved cookies from login-and-wait.", { url: z.string().url().describe("The URL of the webpage to screenshot"), fullPage: z.boolean().optional().default(true).describe("Whether to capture the full page or just the viewport"), width: z.number().optional().default(1920).describe("Viewport width in pixels"), height: z.number().optional().default(1080).describe("Viewport height in pixels"), format: z.enum(['png', 'jpeg', 'webp']).optional().default('png').describe("Image format for the screenshot"), quality: z.number().min(0).max(100).optional().describe("Quality of the image (0-100), only applicable for jpeg and webp"), waitFor: z.enum(['load', 'domcontentloaded', 'networkidle0', 'networkidle2']).optional().default('networkidle2').describe("When to consider the page loaded"), delay: z.number().optional().default(0).describe("Additional delay in milliseconds to wait after page load"), useSavedAuth: z.boolean().optional().default(true).describe("Whether to use saved cookies from previous login"), reuseAuthPage: z.boolean().optional().default(false).describe("Whether to use the existing authenticated page instead of creating a new one"), useDefaultBrowser: z.boolean().optional().default(false).describe("Whether to use the system's default browser instead of Puppeteer's bundled Chromium"), visibleBrowser: z.boolean().optional().default(false).describe("Whether to show the browser window (non-headless mode)") }, async ({ url, fullPage, width, height, format, quality, waitFor, delay, useSavedAuth, reuseAuthPage, useDefaultBrowser, visibleBrowser }) => { let page: Page | null = null; let shouldClosePage = true; try { // Initialize browser with appropriate options const isHeadless = !visibleBrowser; const browserInstance = await initBrowser(isHeadless, useDefaultBrowser && visibleBrowser); // Check if we should reuse the authenticated page if (reuseAuthPage && persistentPage && !persistentPage.isClosed()) { page = persistentPage; shouldClosePage = false; // Navigate to the new URL if different const currentUrl = page.url(); if (currentUrl !== url) { await page.goto(url, { waitUntil: waitFor as any, timeout: 30000 }); } } else { // Create a new page page = await browserInstance.newPage(); // Load saved cookies if requested if (useSavedAuth) { const cookies = await loadCookies(url); if (cookies.length > 0) { await page.setCookie(...cookies); } } // Set viewport await page.setViewport({ width, height }); // Set user agent to avoid bot detection await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); // Additional anti-detection measures for Google await page.evaluateOnNewDocument(() => { // Remove webdriver property delete (window.navigator as any).webdriver; // Override the plugins property to add fake plugins Object.defineProperty(window.navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] }); // Override the languages property Object.defineProperty(window.navigator, 'languages', { get: () => ['en-US', 'en'] }); // Override permissions Object.defineProperty(window.navigator, 'permissions', { get: () => ({ query: () => Promise.resolve({ state: 'granted' }) }) }); }); // Navigate to the URL await page.goto(url, { waitUntil: waitFor as any, timeout: 30000 }); } // Optional delay if (delay > 0) { await new Promise(resolve => setTimeout(resolve, delay)); } // Prepare screenshot options const screenshotOptions: any = { encoding: 'base64', fullPage, type: format }; // Add quality option for jpeg and webp if ((format === 'jpeg' || format === 'webp') && quality !== undefined) { screenshotOptions.quality = quality; } // Take screenshot const screenshot = await page.screenshot(screenshotOptions) as string; // Get page title and final URL for context const pageTitle = await page.title(); const finalUrl = page.url(); // If using a new page, save any new cookies if (!reuseAuthPage && useSavedAuth) { const currentCookies = await page.cookies(); if (currentCookies.length > 0) { await saveCookies(url, currentCookies); } } // Determine browser type for response const browserType = useDefaultBrowser && visibleBrowser ? 'default browser' : 'Puppeteer browser'; const browserMode = visibleBrowser ? 'visible' : 'headless'; return { content: [ { type: "text", text: `Screenshot captured successfully!\n\nBrowser: ${browserType} (${browserMode})\nPage Title: ${pageTitle}\nFinal URL: ${finalUrl}\nFormat: ${format}\nDimensions: ${width}x${height}\nFull Page: ${fullPage}\nUsed saved auth: ${useSavedAuth}\nReused auth page: ${reuseAuthPage}` }, { type: "image", data: screenshot, mimeType: `image/${format}` } ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { isError: true, content: [ { type: "text", text: `Error capturing screenshot: ${errorMessage}`, }, ], }; } finally { // Only close the page if it's not the persistent one or if we should close it if (page && shouldClosePage && page !== persistentPage) { await page.close().catch(() => {}); } } } );
  • Helper function to load authentication cookies for a given URL/domain from persistent storage, used by screenshot-page for auth support.
    async function loadCookies(url: string): Promise<Cookie[]> { try { const domain = getDomainFromUrl(url); const cookiesPath = path.join(cookiesDir, `${domain}.json`); const cookiesData = await fsPromises.readFile(cookiesPath, 'utf-8'); return JSON.parse(cookiesData); } catch { return []; } }
  • Helper function to save cookies for a domain after page load, enabling persistent authentication across tool calls.
    async function saveCookies(url: string, cookies: Cookie[]) { await ensureCookiesDir(); const domain = getDomainFromUrl(url); const cookiesPath = path.join(cookiesDir, `${domain}.json`); await fsPromises.writeFile(cookiesPath, JSON.stringify(cookies, null, 2)); }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ananddtyagi/webpage-screenshot-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server