capture_element
Take screenshots of specific webpage elements using CSS selectors to document UI components or capture targeted content.
Instructions
Capture a screenshot of a specific element on a webpage
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The URL of the webpage | |
| selector | Yes | CSS selector for the element to capture | |
| viewport | No | Viewport configuration | |
| standardDelay | No | Whether to apply standard 2.5s delay after networkidle2 for better stability |
Implementation Reference
- src/screenshot.js:230-306 (handler)The `captureElement` method in the `ScreenshotCapture` class that implements the core tool logic: validates URL and selector, navigates to page with Puppeteer, captures element screenshot, processes image with Sharp for resizing if needed, and returns base64 data.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:121-166 (schema)The tool definition object including name, description, and inputSchema for validating parameters of the capture_element tool.{ 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:179-183 (registration)Registers the capture_element tool (included in the `tools` array) by handling ListToolsRequestSchema and returning the list of available tools.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: tools }; });
- index.js:218-241 (registration)Handles incoming calls to the capture_element tool in the CallToolRequestSchema handler by invoking the captureElement method and formatting the image response.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)}` } ] };