The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Chrome’s chrome.tabs.captureVisibleTab() captures the active tab’s visible viewport—not an arbitrary rectangle. To capture a user-selected area, take one viewport screenshot, let the user select a rectangle over it, then crop that rectangle from the screenshot in extension code. The example below uses a Manifest V3 popup and a canvas, and maps the displayed selection back to the screenshot’s actual pixel dimensions.
How the capture-and-crop workflow works
A still-image selection involves two separate operations: Chrome captures the visible viewport as an image data URL, and your extension crops the chosen rectangle from that image. The capture API has no rectangle parameter. See Chrome’s chrome.tabs API reference.
- The user clicks the extension’s toolbar button, opening its popup.
- The user presses a button in the popup. The extension captures the active tab once.
- The extension draws the returned image into a canvas and lets the user drag a selection over it.
- The extension converts the selection from displayed canvas coordinates to source-image pixels, crops locally, and downloads the result.
The conversion matters because the displayed canvas may be scaled to fit the popup, and the bitmap may have different pixel dimensions from the displayed image. Calculate the scale from the image’s actual dimensions and the canvas dimensions; do not assume a particular device-pixel ratio.
Set up a minimal Manifest V3 extension
1. Create the manifest
Create a folder, for example area-capture, and save the following as manifest.json. The activeTab permission gives temporary access following a user invocation; it is sufficient here, so the extension does not request broad access to every site. The tabs permission is not needed merely to call the tabs namespace.
#1 Best Overall
{
"manifest_version": 3,
"name": "Area Capture",
"version": "1.0.0",
"description": "Capture and crop an area of the active tab.",
"permissions": ["activeTab"],
"action": {
"default_popup": "popup.html",
"default_title": "Capture an area"
}
}
2. Add the popup interface
Save this as popup.html. The canvas is the visible screenshot preview and selection surface. Its CSS maximum width scales the preview to the popup; the JavaScript uses the canvas’s intrinsic dimensions for the crop mapping.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font: 14px sans-serif; margin: 12px; width: 360px; }
button { margin: 0 6px 8px 0; }
canvas { display: block; max-width: 100%; height: auto; border: 1px solid #888; touch-action: none; }
#status { min-height: 1.3em; }
</style>
</head>
<body>
<button id="capture">Capture visible tab</button>
<button id="save" disabled>Save selected area</button>
<p id="status">Capture a tab, then drag over the image to select an area.</p>
<canvas id="preview"></canvas>
<script src="popup.js"></script>
</body>
</html>
3. Capture once and crop the selection
Save this as popup.js. Pointer coordinates are measured relative to the displayed canvas rectangle and scaled into its intrinsic bitmap coordinates. The canvas bitmap itself is created at the screenshot’s natural dimensions. Cropping uses those same source-pixel coordinates.
const captureButton = document.querySelector("#capture");
const saveButton = document.querySelector("#save");
const status = document.querySelector("#status");
const canvas = document.querySelector("#preview");
const ctx = canvas.getContext("2d");
let sourceImage = null;
let selection = null;
let dragStart = null;
let isDragging = false;
captureButton.addEventListener("click", async () => {
status.textContent = "Capturing visible tab…";
saveButton.disabled = true;
selection = null;
sourceImage = null;
try {
const dataUrl = await chrome.tabs.captureVisibleTab({ format: "png" });
const image = new Image();
image.onload = () => {
sourceImage = image;
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
drawPreview();
status.textContent = "Drag over the image to select a rectangle.";
};
image.onerror = () => {
status.textContent = "The captured image could not be decoded.";
};
image.src = dataUrl;
} catch (error) {
status.textContent = `Capture failed: ${error.message}`;
}
});
function canvasPoint(event) {
const rect = canvas.getBoundingClientRect();
return {
x: (event.clientX - rect.left) * (canvas.width / rect.width),
y: (event.clientY - rect.top) * (canvas.height / rect.height)
};
}
function normalizedRect(a, b) {
const left = Math.min(a.x, b.x);
const top = Math.min(a.y, b.y);
const right = Math.max(a.x, b.x);
const bottom = Math.max(a.y, b.y);
return { x: left, y: top, width: right - left, height: bottom - top };
}
function drawPreview() {
if (!sourceImage) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(sourceImage, 0, 0);
if (selection) {
ctx.save();
ctx.fillStyle = "rgba(0, 110, 255, 0.22)";
ctx.strokeStyle = "#006eff";
ctx.lineWidth = Math.max(1, canvas.width / 500);
ctx.fillRect(selection.x, selection.y, selection.width, selection.height);
ctx.strokeRect(selection.x, selection.y, selection.width, selection.height);
ctx.restore();
}
}
canvas.addEventListener("pointerdown", event => {
if (!sourceImage) return;
canvas.setPointerCapture(event.pointerId);
dragStart = canvasPoint(event);
selection = normalizedRect(dragStart, dragStart);
isDragging = true;
saveButton.disabled = true;
drawPreview();
});
canvas.addEventListener("pointermove", event => {
if (!isDragging || !dragStart) return;
selection = normalizedRect(dragStart, canvasPoint(event));
drawPreview();
});
function finishSelection(event) {
if (!isDragging || !dragStart) return;
selection = normalizedRect(dragStart, canvasPoint(event));
isDragging = false;
dragStart = null;
const usable = selection.width > 0 && selection.height > 0;
saveButton.disabled = !usable;
status.textContent = usable
? `Selected ${Math.round(selection.width)} × ${Math.round(selection.height)} source pixels.`
: "The selection is empty. Drag a rectangle over the image.";
drawPreview();
}
canvas.addEventListener("pointerup", finishSelection);
canvas.addEventListener("pointercancel", finishSelection);
saveButton.addEventListener("click", () => {
if (!sourceImage || !selection || !selection.width || !selection.height) return;
const x = Math.floor(selection.x);
const y = Math.floor(selection.y);
const right = Math.ceil(selection.x + selection.width);
const bottom = Math.ceil(selection.y + selection.height);
const width = Math.min(canvas.width, right) - x;
const height = Math.min(canvas.height, bottom) - y;
if (width <= 0 || height <= 0) return;
const output = document.createElement("canvas");
output.width = width;
output.height = height;
output.getContext("2d").drawImage(
sourceImage, x, y, width, height, 0, 0, width, height
);
output.toBlob(blob => {
if (!blob) {
status.textContent = "The selected area could not be encoded.";
return;
}
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "selected-area.png";
link.click();
setTimeout(() => URL.revokeObjectURL(url), 1000);
status.textContent = `Saved ${width} × ${height} pixels as PNG.`;
}, "image/png");
});
4. Load and try it
- Open
chrome://extensionsin Chrome and enable Developer mode. - Choose Load unpacked and select the
area-capturefolder. - Open a regular web page, click the extension icon, and choose Capture visible tab.
- Drag over the preview and choose Save selected area. The extension downloads a PNG crop.
This example captures the viewport as it is visible at that moment. It does not capture content outside the viewport or scroll the page to reveal additional content. The selection applies to the screenshot pixels, not to a live DOM element.
Rank #2
- [Beautiful and Effective] It adopts special process technology with widened sealing surface of water outlet to ensure close contact with the sealing gasket of sprinkler. 95% of shower head can achieve good water sealing effect without thread seal tape, so there’s no need to worry about the beauty of bathroom will be affected by the residue of thread seal tapes.
- [Durable and Safe] The pipe is made of marine-grade 304 stainless steel with over twice strength of ordinary brass, good resistance to acid, alkali and salt, long-term corrosion resistance to avoid shower head blockage due to rust residues, especially suitable for hard water and hot spring water.
- [Multi-layer Electroplating] Multi-layer nickel-chromium electroplating process technology, nickel layer can resist corrosion with adhesion, chromium layer can resist scratches with shining effect. The layer is always bright and shining without falling off even after long period of use.
- [Installation and Specifications] Detailed instructions ensure worry-free installation. The product is 3 in long, the thread specification of inlet is 1/2"-14 NPT, suitable for standard shower arm. The thread specification of outlet is 1/2"-14 NPT (compatible with 1/2" IPS thread), suitable for sprinkles of standard interface.
- [After-sales Service] In case of any problems or complaints during use or installation, please don’t hesitate to contact us and we will respond with solutions within 24 hours. It’s always our persistence and belief to provide high-quality products and satisfactory customer services.
Permissions, constraints, and API choices
Use the narrow permission that matches the interaction
captureVisibleTab() requires either activeTab or <all_urls>. A user-invoked extension commonly uses activeTab to obtain temporary access without asking for broad site access. Chrome documents that sensitive pages, including chrome: pages, can be captured only with activeTab; access to file URLs requires the user to grant file access. A capture may still be unavailable on a restricted or otherwise inaccessible page.
If you add script injection—for example, to inspect or manipulate page DOM—chrome.scripting.executeScript() requires the scripting permission plus matching host permissions, or activeTab. It can target a tab and specific frames. See the chrome.scripting API reference. The crop example above does not inject scripts because the screenshot alone supplies the selection surface.
Choose a stream API only when you need a stream
| Need | API | What it does |
|---|---|---|
| One visible-viewport screenshot to crop | chrome.tabs.captureVisibleTab() |
Returns an image data URL; crop it after capture. |
| Ongoing tab video/audio or a recording | chrome.tabCapture |
Captures tab media as a stream and is initiated after a user invocation. |
| DOM APIs in an MV3 background workflow | chrome.offscreen |
Creates a hidden extension document that can use DOM APIs unavailable in the service worker. |
Chrome’s screen-capture guide describes getDisplayMedia() as presenting a browser chooser for a tab, window, or screen. For a known active tab without that chooser, it describes tabCapture; from Chrome 116, a service worker can obtain a stream ID after user invocation and pass it to an offscreen document. Those stream approaches solve recording and media-stream needs, not the simple still-image crop here. See the chrome.tabCapture reference.
Rank #3
- [Beautiful and Effective] It adopts special process technology with widened sealing surface of water outlet to ensure close contact with the sealing gasket of sprinkler. 95% of shower head can achieve good water sealing effect without thread seal tape, so there’s no need to worry about the beauty of bathroom will be affected by the residue of thread seal tapes.
- [Durable and Safe] The pipe is made of marine-grade 304 stainless steel with over twice strength of ordinary brass, good resistance to acid, alkali and salt, long-term corrosion resistance to avoid shower head blockage due to rust residues, especially suitable for hard water and hot spring water.
- [Multi-layer Electroplating] Multi-layer nickel-chromium electroplating process technology, nickel layer can resist corrosion with adhesion, chromium layer can resist scratches with shining effect. The layer is always bright and shining without falling off even after long period of use.
- [Installation and Specifications] Detailed instructions ensure worry-free installation. The product is 6 in long, the thread specification of inlet is 1/2"-14 NPT, suitable for standard shower arm. The thread specification of outlet is 1/2"-14 NPT (compatible with 1/2" IPS thread), suitable for sprinkles of standard interface.
- [After-sales Service] In case of any problems or complaints during use or installation, please don’t hesitate to contact us and we will respond with solutions within 24 hours. It’s always our persistence and belief to provide high-quality products and satisfactory customer services.
MV3 processing, selection behavior, and extensions to the example
Why the example keeps image work in the popup
A Manifest V3 service worker has no DOM, so it cannot use DOM image or canvas APIs directly. An extension popup is a document and can use Image, canvas, pointer events, and downloads as shown. If your background workflow needs DOM-based processing, Chrome’s offscreen API reference documents a hidden extension document for that purpose and availability in Chrome 109+ MV3. Chrome’s screen-capture guide also describes offscreen documents for media capture and processing.
Selection and output details
- The sample supports dragging in any direction and normalizes the start and end points into a top-left rectangle.
- It rounds outward to whole source pixels when cropping, so a fractional boundary includes the touched edge pixels.
- The output is PNG. To produce JPEG or WebP, pass a supported MIME type to
toBlob()and choose a matching filename; verify the browser’s encoder support for the desired format. - For a keyboard-accessible or touch-focused selector, add explicit controls for moving and resizing the rectangle and announce its dimensions. The pointer implementation is a compact baseline, not a complete accessibility interface.
- To capture a particular DOM element rather than a user-drawn rectangle, you can use a content script to determine its bounds, but you still need to account for page scrolling, frame boundaries, and the screenshot’s pixel scale. Script injection brings the additional permission requirements described above.
Performance, reliability, and cost considerations
Chrome describes captureVisibleTab() as expensive and limits it to at most two calls per second (documented for Chrome 92+). Capture once when the user asks, then update the selection overlay locally; do not recapture as the pointer moves. Repeated screenshots waste work and can hit the API limit.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallThe crop itself is local canvas work. Large viewport bitmaps and high-resolution displays consume more memory than small images, and creating extra full-size canvases can increase that cost. This example holds one source image and creates a second canvas only for the selected crop. If you process very large images, release temporary references when finished and avoid retaining multiple full-size copies.
Rank #4
- VERSATILE REACH - This extension set includes 3, 6, and 10-inch extension bars, providing you with the flexibility to access tight spaces and reach fasteners in hard-to-reach areas, making it perfect for auto repair and home improvement projects
- FLEXIBLE CONNECTION - The included 3/8" drive universal joint socket allows you to work at various angles, offering flexibility for a wide range of repair and maintenance tasks, improving both convenience and overall productivity
- PREMIUM DURABILITY - Made from high-quality, hardened chrome vanadium steel, this 3/8" socket extension set is designed for long-lasting performance with exceptional rust resistance, ensuring it can withstand demanding tasks for years
- ANTI-SLIP GRIP - The chrome-plated, mirror-finished surface combined with an anti-slip design ensures easy maintenance and secure handling, giving you more control and preventing slippage during high-torque applications
- EFFORTLESS PERFORMANCE - Featuring extension bars and a universal joint socket, this set locks securely into place, improving work efficiency by allowing you to quickly and precisely complete tasks without interruptions
There is no server request or screenshot-service fee in this extension workflow; the browser performs the capture and crop. Reliability depends on permission/access to the active tab and successful image decoding and canvas encoding. The example reports capture, decode, and encoding failures rather than silently saving an empty file.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting
Capture rejects or returns no usable image
- Cause: The popup was not opened through the extension’s user interaction, the active tab is restricted, or temporary access is unavailable.
- Fix: Test by clicking the extension toolbar action on a normal website and then pressing the capture button. Check Chrome’s extension error display at
chrome://extensions. For file URLs, grant file access in the extension’s details if you need those pages.
The preview appears blank or reports a decode error
- Cause: The image has not loaded, or decoding failed.
- Fix: Wait for the image load handler before drawing; this example does so. Confirm that the screenshot data URL is non-empty and check the extension page’s console for errors.
The crop is shifted or the wrong size
- Cause: Display coordinates were used directly against source pixels, or the code assumed a fixed device-pixel ratio.
- Fix: Scale the pointer coordinates using
canvas.width / canvas.getBoundingClientRect().widthand the corresponding height ratio, as incanvasPoint(). Keep the canvas intrinsic dimensions equal to the image’s natural dimensions.
The image is cut off or the desired area is not on screen
- Cause:
captureVisibleTab()captures only the visible viewport. - Fix: Scroll the page to expose the target before capturing, or build a separate full-page strategy. The API does not accept a rectangle or return off-viewport page content.
It works once, then captures are throttled
- Cause: The extension is making captures too frequently; Chrome documents a maximum of two calls per second.
- Fix: Take one image at the start of the selection interaction and perform drag, resize, and crop operations against that bitmap.
Or skip the browser setup
If your goal is a URL screenshot rather than a user-drawn region inside an extension, ScreenshotNeo provides a website screenshot API and MCP server. The endpoint returns a screenshot or PDF; it does not replace the in-extension rectangle-selection code above. This one-call example captures a page image, which you can crop downstream if you need a particular region. See the ScreenshotNeo documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
- Cookie and consent banners are accepted and removed, along with known newsletter popups and chat widgets, before the shot; each cleanup step can be turned off.
- Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; response headers identify the page verdict and billing status.
- An MCP server offers
take_screenshot,get_page_info, andcapture_pdftools for AI agents and MCP clients. - The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo and get 1,000 free screenshots a month with no card.
Recommended Free Tools
Best Value
- 【Premium CR-V】Made from premium chrome vanadium steel with mirror polish finish for industrial, mechanic or construction work.
- 【Set Include】3-piece 1/4" Dr.: 2-inch, 4-inch, 6-inch, 3-piece 3/8" Dr.: 3-inch, 6-inch, 10-inch, 3-piece 1/2" Dr.: 3-inch, 5-inch, 10-inch.
- 【Enhanced Torque Force】The spring-loaded detent ball system at the end of bars locks socket into place for security and prevents dropping. Knurled handle for easy hand turning loosened fasteners.
- 【Easy to Organize】It comes with a durable blow-molded carrying case for easy transportation, safe storage, and quick organization.
- 【Service Guarantee】All MIXPOWER Tools meet or exceed ANSI performance standards. It comes with 1 year quality guarantee.
Frequently Asked Questions
Does captureVisibleTab capture a selected DOM element by itself?
No. It captures the visible viewport; the extension must crop the resulting image or use a different approach for its specific requirement.
Can this workflow capture an area outside the current viewport?
No. The screenshot contains only what is visible when capture occurs.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

