How to Capture Part of an Autodesk Forge Viewer Model
Select and isolate Forge Viewer objects, frame them, capture with getScreenShot, and crop precisely with canvas or browser clipping.
To capture only part of an Autodesk Forge Viewer model, select the target objects, isolate them, fit the camera to the isolated selection, and then call viewer.getScreenShot(width, height, callback). The Viewer screenshot method controls the rendered image dimensions; it does not crop an arbitrary rectangle. For a precise rectangular crop, capture the viewer and crop the returned image with JavaScript, or convert model coordinates to screen coordinates with viewer.worldToClient() and use a headless browser clip.
Choose the capture method
| Goal | Recommended method |
|---|---|
| Show one selected object or assembly | Select its database IDs, isolate them, fit the view, then call getScreenShot. |
| Hide surrounding objects manually | Use the Model Browser context menu: Isolate, Hide selected, Show all objects, Focus, or Section. |
| Crop a pixel rectangle from the viewer | Capture the viewer, then crop the image on a canvas. |
| Crop a model-space region automatically | Project bounding-box corners with worldToClient, then pass the resulting rectangle to a browser screenshot clip. |
UI-only workflow
- Open the model in Autodesk Viewer.
- Use the Model Browser to search for and select the object or objects.
- Open the context menu and choose Isolate. Use Hide selected when you need to remove specific objects while leaving the rest visible.
- Choose Focus to center the camera on the selection. Use Section when an interior cutaway is required.
- Open the Export Data controls and choose Screenshot.
This workflow captures what is visible in the viewer. It is useful for one-off images, but repeatable exports should use the Viewer JavaScript API.
Capture a selected part with the Viewer API
The key is to wait for selection and visibility changes before taking the screenshot. A selection change gives you database IDs; isolation changes the visible scene; fitting the view makes the selected part occupy the frame.
1. Read the selected database IDs
viewer.addEventListener(
Autodesk.Viewing.SELECTION_CHANGED_EVENT,
function (event) {
const dbIds = event.dbIdArray || viewer.getSelection();
console.log("Selected database IDs:", dbIds);
}
);
2. Isolate the selection and fit the camera
function isolateAndFrame(viewer, dbIds) {
if (!Array.isArray(dbIds) || dbIds.length === 0) {
throw new Error("Select at least one model object");
}
viewer.isolate(dbIds);
viewer.fitToView(dbIds);
}
const selectedIds = viewer.getSelection();
isolateAndFrame(viewer, selectedIds);
For a multi-model viewer, pass the appropriate model to the visibility manager and fit operation. If the selection belongs to a particular model, keep that model reference with the IDs so that visibility calls are applied to the correct instance.
3. Wait for the view to settle before capture
function waitForViewerRender(viewer, frames = 2) {
return new Promise((resolve) => {
function next() {
if (frames-- <= 0) return resolve();
requestAnimationFrame(next);
}
requestAnimationFrame(next);
});
}
async function captureSelection(viewer, dbIds, width = 1600, height = 1000) {
isolateAndFrame(viewer, dbIds);
await waitForViewerRender(viewer, 3);
return new Promise((resolve, reject) => {
viewer.getScreenShot(width, height, (blobOrDataUrl) => {
if (!blobOrDataUrl) {
reject(new Error("Viewer returned an empty screenshot"));
return;
}
resolve(blobOrDataUrl);
});
});
}
const image = await captureSelection(viewer, viewer.getSelection());
The exact screenshot callback value can vary with the Viewer SDK version and application wrapper. Treat the returned value according to your integration: it may be a data URL, an image blob, or a value your wrapper converts into a downloadable file.
Crop a returned screenshot with JavaScript
getScreenShot renders the viewer at the requested dimensions. It does not mean “crop this rectangle.” To crop a rectangle, load the returned image into an Image, draw it into a canvas, and use source coordinates for the crop.
function cropImage(dataUrl, crop) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
const canvas = document.createElement("canvas");
canvas.width = crop.width;
canvas.height = crop.height;
const context = canvas.getContext("2d");
context.drawImage(
image,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height
);
resolve(canvas.toDataURL("image/png"));
};
image.onerror = reject;
image.src = dataUrl;
});
}
const screenshotDataUrl = await captureSelection(viewer, [1234], 1600, 1000);
const cropped = await cropImage(screenshotDataUrl, {
x: 250,
y: 120,
width: 900,
height: 700
});
const link = document.createElement("a");
link.href = cropped;
link.download = "selected-part.png";
link.click();
Coordinates are pixels in the returned screenshot, with (0, 0) at the top-left. If your viewer element is displayed at a different CSS size than the requested screenshot dimensions, scale the crop rectangle to the rendered image dimensions first.
Automate a crop from model coordinates
When the crop should follow a model-space bounding box, project its corners into screen coordinates. viewer.worldToClient() converts a world point to viewer coordinates. Compute the minimum and maximum projected coordinates, then clip the browser page.
function projectedRect(viewer, bounds) {
const corners = [
new THREE.Vector3(bounds.min.x, bounds.min.y, bounds.min.z),
new THREE.Vector3(bounds.min.x, bounds.min.y, bounds.max.z),
new THREE.Vector3(bounds.min.x, bounds.max.y, bounds.min.z),
new THREE.Vector3(bounds.min.x, bounds.max.y, bounds.max.z),
new THREE.Vector3(bounds.max.x, bounds.min.y, bounds.min.z),
new THREE.Vector3(bounds.max.x, bounds.min.y, bounds.max.z),
new THREE.Vector3(bounds.max.x, bounds.max.y, bounds.min.z),
new THREE.Vector3(bounds.max.x, bounds.max.y, bounds.max.z)
];
const points = corners.map((point) => viewer.worldToClient(point));
const xs = points.map((point) => point.x);
const ys = points.map((point) => point.y);
return {
x: Math.floor(Math.min(...xs)),
y: Math.floor(Math.min(...ys)),
width: Math.ceil(Math.max(...xs) - Math.min(...xs)),
height: Math.ceil(Math.max(...ys) - Math.min(...ys))
};
}
const box = new THREE.Box3(
new THREE.Vector3(-2, -1, 0),
new THREE.Vector3(4, 3, 5)
);
const clip = projectedRect(viewer, box);
console.log(clip);
Use the rectangle with a browser automation tool after the viewer has rendered. With Playwright, the page-level screenshot clip is expressed in browser CSS pixels:
await page.screenshot({
path: "model-region.png",
clip: {
x: clip.x,
y: clip.y,
width: clip.width,
height: clip.height
}
});
Account for the viewer container’s offset within the page. If worldToClient returns coordinates relative to the viewer canvas, add the canvas bounding rectangle’s left and top before passing the clip to the page screenshot method.
Full example: select, isolate, frame, and save
async function exportSelectedPart(viewer) {
const dbIds = viewer.getSelection();
if (!dbIds || dbIds.length === 0) {
throw new Error("No objects selected");
}
viewer.isolate(dbIds);
viewer.fitToView(dbIds);
await waitForViewerRender(viewer, 3);
const dataUrl = await new Promise((resolve, reject) => {
viewer.getScreenShot(1800, 1200, (result) => {
if (!result) reject(new Error("Screenshot failed"));
else resolve(result);
});
});
const cropped = await cropImage(dataUrl, {
x: 0,
y: 0,
width: 1800,
height: 1200
});
const anchor = document.createElement("a");
anchor.href = cropped;
anchor.download = `forge-selection-${dbIds.join("-")}.png`;
anchor.click();
}
// Run after the user selects one or more objects.
await exportSelectedPart(viewer);
Aspect ratio and output quality
- Choose
widthandheightthat match the viewer’s intended aspect ratio. This avoids unexpected framing and wasted pixels. - Request a larger render when you need a print or documentation image, then downsample once during export.
- Fit the isolated selection before capture. A screenshot of the current camera can leave the selected part small or partly outside the frame.
- Use a crop only after the rendered image exists. A crop rectangle cannot recover geometry that was outside the original camera view.
- For transparent output or post-processing, export the image into your own canvas pipeline and choose the format required by your document system.
Sections, hidden objects, and multiple selections
Isolate versus hide
Use isolate when the goal is a part-only image. Use hide selected when context from the surrounding model should remain visible. Restore the scene with Show all objects before the next capture if your application reuses the same viewer.
Section views
Section controls are useful when the target is inside a building or assembly. Apply the section plane, wait for the render to settle, fit the visible selection, and then capture. A section plane changes visibility; it does not itself define a pixel crop.
Multiple models
In a federated or multi-model scene, database IDs are scoped to their model. Track the model associated with each selected ID and apply visibility and fit operations consistently. Mixing IDs from different models can produce an empty or incomplete result.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| The screenshot contains the whole model | The selection was never isolated. | Call viewer.isolate(dbIds) before fitting and capture. |
| The selected part is tiny | The camera stayed on its previous view. | Call viewer.fitToView(dbIds) and wait for rendering. |
| The image is blank | Capture ran before the model or visibility update finished. | Wait for model loading, isolation-change handling, and a few animation frames. |
| The crop is offset | Viewer coordinates and page coordinates have different origins. | Add the viewer canvas bounding rectangle offset and account for device pixel ratio. |
| Some selected objects disappear | IDs belong to another model or an active section plane clips them. | Use the correct model reference and temporarily inspect section settings. |
| The result has the wrong proportions | Requested dimensions do not match the desired aspect ratio. | Preserve the viewer aspect ratio, then crop or resize afterward. |
| Callback returns no image | The viewer is not ready or the SDK wrapper handles the callback differently. | Confirm the Viewer SDK version, wait for rendering, and inspect the callback value before saving. |
| Browser clip misses the target | The projected rectangle is relative to the canvas, not the page. | Translate by the canvas’s page offset and clamp the rectangle to viewport bounds. |
Performance, reliability, and cost considerations
- Reuse an initialized viewer when exporting several parts. Reinitializing the viewer for every image adds model loading time.
- Capture after visibility and camera changes settle. A short render wait is more reliable than taking the first frame after an API call.
- Batch your export queue and avoid many simultaneous high-resolution renders in the same browser tab.
- Keep the original database IDs and camera state with each image so exports can be reproduced after model updates.
- Large screenshots consume more memory during canvas operations. Release temporary canvases and blobs after saving.
- Headless browser clipping adds browser startup and page-rendering cost, but it is the most flexible option for automated pixel regions.
- The Viewer API itself does not provide a general arbitrary-region crop. Use canvas or browser clipping when the output must be a precise rectangle.
Or skip the browser setup
ScreenshotNeo can capture a URL with one request, including pages that embed your viewer. Its cleanup step accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers. It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
For the complete option list and request details, see the ScreenshotNeo documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo includes full-page capture with lazy images loaded, CSS-selector element capture, custom JavaScript and CSS, click and wait controls, request blocking, custom headers and cookies, device and viewport settings, retina scale, caching, signed links, asynchronous jobs, webhooks, bulk capture, and PDF output. It may be useful when your Forge Viewer page is already deployed and you need repeatable URL-level captures around your existing browser workflow.
Create a free ScreenshotNeo account for 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots.
FAQ
Does getScreenShot crop to a selected object automatically?
No. It renders the viewer at the dimensions you request. Isolate and fit the object first, then crop separately if you need a precise rectangle.
Can I capture an object without hiding the rest of the model?
Yes. Leave the scene visible and use the current camera, or hide selected objects selectively. For a part-only image, isolate the target.
How do I capture a region defined in model coordinates?
Project the region’s bounding-box corners with worldToClient(), calculate the screen rectangle, and use a browser screenshot clip after translating coordinates to page space.
Why is the output different from the viewer window?
The screenshot dimensions determine the rendered output. Preserve the viewer’s aspect ratio and explicitly set the camera before capture.
Can this work with a section cut?
Yes. Apply the section controls, wait for the clipped view to render, fit the visible selection, and capture.


