capture_element
Snap a screenshot of a specific webpage element using a CSS selector. Configure viewport settings for device responsiveness and ensure stability with optional delays.
Instructions
Capture a screenshot of a specific element on a webpage
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| selector | Yes | CSS selector for the element to capture | |
| standardDelay | No | Whether to apply standard 2.5s delay after networkidle2 for better stability | |
| url | Yes | The URL of the webpage | |
| viewport | No | Viewport configuration |
Implementation Reference
- src/screenshot.js:230-306 (handler)Core handler function that launches a browser page, navigates to the URL, waits for network idle and standard delay, locates the element by selector, captures its screenshot, processes it with Sharp for metadata and resizing if over 8000px dimension, and returns base64 PNG data with metadata.async captureElement(url, selector, options = {}) { const validatedUrl = validateUrl(url); const validatedSelector = sanitizeSelector(selector); if (!validatedSelector) { throw createError('Invalid selector provided', 'INVALID_SELECTOR'); } await this.initialize(); const page = await this.browser.newPage(); try { await this.configureViewport(page, options.viewport); await page.goto(validatedUrl, { waitUntil: 'networkidle2' }); // Standard delay after networkidle2 for better stability const standardDelay = options.standardDelay !== false ? 2500 : 0; if (standardDelay > 0) { await new Promise(resolve => setTimeout(resolve, standardDelay)); } const element = await page.$(validatedSelector); if (!element) { throw createError(`Element not found: ${validatedSelector}`, 'ELEMENT_NOT_FOUND'); } // * Take the element screenshot const screenshotBase64 = await element.screenshot({ type: 'png', encoding: 'base64' }); // * Decode base64 to buffer for sharp processing let screenshotBuffer = Buffer.from(screenshotBase64, 'base64'); let metadata; try { metadata = await sharp(screenshotBuffer).metadata(); } catch (err) { throw createError('Failed to read element screenshot metadata', 'IMAGE_METADATA_ERROR', { originalError: err.message }); } // * Check if resizing is needed const maxDimension = 8000; if (metadata.width > maxDimension || metadata.height > maxDimension) { // * Calculate scale factor to fit within 8000x8000 const scale = Math.min(maxDimension / metadata.width, maxDimension / metadata.height); const newWidth = Math.floor(metadata.width * scale); const newHeight = Math.floor(metadata.height * scale); try { screenshotBuffer = await sharp(screenshotBuffer) .resize({ width: newWidth, height: newHeight }) .png() .toBuffer(); } catch (err) { throw createError('Failed to resize element screenshot image', 'IMAGE_RESIZE_ERROR', { originalError: err.message }); } } // * Encode back to base64 const finalBase64 = screenshotBuffer.toString('base64'); return { success: true, data: finalBase64, metadata: { url: validatedUrl, selector: validatedSelector, timestamp: new Date().toISOString(), imageWidth: metadata.width, imageHeight: metadata.height } }; } finally { await page.close(); } }
- index.js:124-164 (schema)JSON Schema defining the input parameters for the capture_element tool, requiring URL and CSS selector, with optional viewport configuration and standard delay flag.inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'The URL of the webpage' }, selector: { type: 'string', description: 'CSS selector for the element to capture' }, viewport: { type: 'object', properties: { preset: { type: 'string', enum: Object.keys(DEVICE_PRESETS), description: 'Device preset (mobile, tablet, desktop)' }, width: { type: 'number', minimum: 100, maximum: 5000, description: 'Viewport width in pixels' }, height: { type: 'number', minimum: 100, maximum: 5000, description: 'Viewport height in pixels' } }, description: 'Viewport configuration' }, standardDelay: { type: 'boolean', default: true, description: 'Whether to apply standard 2.5s delay after networkidle2 for better stability' } }, required: ['url', 'selector']
- index.js:121-166 (registration)Tool registration object added to the tools list returned by listToolsRequestHandler, including name, description, and input schema.{ name: 'capture_element', description: 'Capture a screenshot of a specific element on a webpage', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'The URL of the webpage' }, selector: { type: 'string', description: 'CSS selector for the element to capture' }, viewport: { type: 'object', properties: { preset: { type: 'string', enum: Object.keys(DEVICE_PRESETS), description: 'Device preset (mobile, tablet, desktop)' }, width: { type: 'number', minimum: 100, maximum: 5000, description: 'Viewport width in pixels' }, height: { type: 'number', minimum: 100, maximum: 5000, description: 'Viewport height in pixels' } }, description: 'Viewport configuration' }, standardDelay: { type: 'boolean', default: true, description: 'Whether to apply standard 2.5s delay after networkidle2 for better stability' } }, required: ['url', 'selector'] } },
- index.js:218-240 (handler)Dispatch handler in the CallToolRequestSchema that receives tool arguments, calls the ScreenshotCapture.captureElement method, and returns MCP-formatted response with text description, base64 image, and metadata.case 'capture_element': const elementResult = await screenshotCapture.captureElement(args.url, args.selector, { viewport: args.viewport, standardDelay: args.standardDelay }); return { content: [ { type: 'text', text: `Element screenshot captured from ${args.url} (selector: ${args.selector})` }, { type: 'image', data: elementResult.data, mimeType: 'image/png' }, { type: 'text', text: `Metadata: ${JSON.stringify(elementResult.metadata, null, 2)}` } ] };