BlogScreenshots on your device
How to Capture a Screen Region by Coordinates in Java
Capture any desktop rectangle in Java with Robot, handle monitors and DPI scaling, save a PNG, and avoid common permission and headless errors.
Use java.awt.Robot with a java.awt.Rectangle. The rectangle’s x and y are screen coordinates, while width and height define the captured region. Robot.createScreenCapture(Rectangle) returns a BufferedImage containing the pixels in that rectangle. Save it with ImageIO.write. See the Oracle Robot API and ImageIO API.
1. Minimal Java example
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class RegionCapture {
public static void main(String[] args) throws AWTException, IOException {
int x = 100;
int y = 80;
int width = 640;
int height = 400;
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("Width and height must be positive");
}
Robot robot = new Robot();
Rectangle region = new Rectangle(x, y, width, height);
BufferedImage image = robot.createScreenCapture(region);
boolean written = ImageIO.write(image, "png", new File("region.png"));
if (!written) {
throw new IOException("No ImageIO writer is available for PNG");
}
}
}
Compile and run it on a graphical desktop:
javac RegionCapture.java
java RegionCapture
The file region.png contains the selected rectangle. The example coordinates are illustrative; choose values that match the target display’s coordinate system.
2. Choosing coordinates correctly
Robot captures screen space, not coordinates relative to your Java window. The origin and monitor arrangement depend on the desktop configuration.
- Primary display:
new Robot()uses the primary screen coordinate system. - Specific display: construct the robot with a
GraphicsDevice. The coordinates passed to its methods use that device’s coordinate system. - Multiple displays: displays can form one virtual desktop, and a secondary display may begin at a negative
xory. Do not assume every monitor starts at(0, 0).
Discover devices and bounds at runtime:
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
GraphicsEnvironment environment =
GraphicsEnvironment.getLocalGraphicsEnvironment();
for (GraphicsDevice device : environment.getScreenDevices()) {
Rectangle bounds = device.getDefaultConfiguration().getBounds();
System.out.printf("%s: x=%d y=%d width=%d height=%d%n",
device.getIDstring(), bounds.x, bounds.y,
bounds.width, bounds.height);
}
To capture a chosen device, use its bounds and bind the robot explicitly:
GraphicsDevice device = environment.getScreenDevices()[0];
Rectangle bounds = device.getDefaultConfiguration().getBounds();
Robot robot = new Robot(device);
BufferedImage image = robot.createScreenCapture(bounds);
When a region crosses monitor boundaries, verify the behavior on each operating system and display layout you support. The API contract does not make every platform’s virtual-screen arrangement identical.
3. High-DPI and scaled displays
Logical UI units and physical pixels can differ on a scaled display. Java provides Robot.createMultiResolutionScreenCapture(Rectangle) (available since Java 9) for cases where a transform maps user space to device space. It can return a base image and a native-resolution variant.
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.awt.image.MultiResolutionImage;
import java.util.List;
Robot robot = new Robot();
Rectangle region = new Rectangle(100, 80, 640, 400);
MultiResolutionImage capture = robot.createMultiResolutionScreenCapture(region);
List<BufferedImage> variants = capture.getResolutionVariants();
for (int i = 0; i < variants.size(); i++) {
BufferedImage variant = variants.get(i);
System.out.printf("variant %d: %dx%d%n", i,
variant.getWidth(), variant.getHeight());
}
Choose the variant that matches your output requirement. If you need a fixed pixel size for processing or comparison, inspect the returned dimensions instead of assuming a one-to-one relationship between logical coordinates and pixels.
4. Production-ready capture method
Validate dimensions, keep capture off the AWT event dispatch thread, and handle construction, permission, and file errors explicitly.
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public final class ScreenCapture {
private ScreenCapture() {}
public static void capture(Rectangle region, File destination)
throws AWTException, IOException {
if (region == null) {
throw new IllegalArgumentException("Region is required");
}
if (region.width <= 0 || region.height <= 0) {
throw new IllegalArgumentException(
"Region width and height must be positive");
}
if (destination == null) {
throw new IllegalArgumentException("Destination is required");
}
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(region);
if (!ImageIO.write(image, "png", destination)) {
throw new IOException("No PNG ImageIO writer is available");
}
}
}
In Swing, call this method from a worker such as SwingWorker rather than the event dispatch thread. Oracle warns that capture can take long enough to freeze a UI. Update Swing components only after the background task completes.
5. Output formats and file handling
PNG is lossless and suitable for text, diagrams, and pixel comparisons. JPEG is smaller for photographic content but introduces compression artifacts. WebP is available only when an ImageIO plugin providing a WebP writer is installed; check the boolean return value for every format.
boolean png = ImageIO.write(image, "png", new File("region.png"));
boolean jpg = ImageIO.write(image, "jpg", new File("region.jpg"));
if (!png && !jpg) {
throw new IOException("No suitable image writer is installed");
}
Create the destination directory before writing, use a unique filename for concurrent captures, and close any streams you open yourself. ImageIO.write accepts a File directly for simple cases.
6. Common errors and fixes
| Error or symptom | Cause | Fix |
|---|---|---|
AWTException while constructing Robot |
Headless environment or low-level input/capture is unavailable. | Run on a graphical desktop session. For server-side rendering, use a browser or screenshot API instead of desktop capture. |
IllegalArgumentException |
The rectangle has zero or negative width or height. | Validate both dimensions before calling createScreenCapture. |
SecurityException or a denied capture |
Operating-system or sandbox permissions prohibit screen capture. | Grant the required screen-recording or desktop-capture permission to the Java process, then retry. The exact flow is platform-specific. |
| Blank, clipped, or wrong monitor image | Coordinates were treated as window-relative, or the virtual desktop has negative offsets/scaling. | Print each GraphicsDevice‘s bounds and calculate coordinates in screen space. |
| UI freezes during capture | Capture and file I/O run on the event dispatch thread. | Move the operation to a worker thread and marshal only the UI update back. |
ImageIO.write returns false |
No writer exists for the requested format. | Use a built-in format such as PNG or install a provider for the required format; always check the return value. |
| Capture works locally but fails in CI | CI is headless or has no interactive display. | Use a virtual display configured by the CI environment, or switch to browser/API capture. |
7. Performance, reliability, and security notes
- Capture only the rectangle you need; larger regions require more pixel memory and more disk I/O.
- Reuse a
Robotfor repeated captures when the same desktop session is used, instead of constructing one for every frame. - Throttle repeated captures and avoid running them on the UI thread.
- Keep coordinates and output paths under application control when input can come from users.
- Desktop capture records whatever is visible, including notifications and sensitive data. Restrict access to saved files and delete temporary images when no longer needed.
- For deterministic automation, control window placement, display scaling, and application state before capture. Desktop pixels can change when another window appears.
8. Or skip the browser setup
If you need screenshots of web pages rather than the physical desktop, ScreenshotNeo returns an image or PDF from one GET request. Cookie and consent banners are accepted and removed before capture, along with 60+ known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response reports its result with X-Page-Verdict and X-Billed headers.
See the ScreenshotNeo API documentation for all options.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);
ScreenshotNeo also supports full-page capture, CSS element selection, dark mode, device presets, custom viewports, retina scale, PDFs, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous jobs, webhooks, bulk capture, usage reporting, and an OpenAPI specification. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is included on every plan. Create a free ScreenshotNeo account.
9. FAQ
Can Robot capture an application window by title?
Not directly. Robot receives a screen-space rectangle. Find the window bounds with platform-specific code or a window-management library, then pass those bounds to createScreenCapture.
Does the rectangle include the cursor?
The API captures screen pixels. Cursor inclusion depends on the desktop environment and capture implementation; do not rely on it for portable output.
Can I use this in a Docker container?
Only if the container has access to a graphical display and the required permissions. A normal headless container cannot construct a usable desktop Robot.
Should I use single- or multi-resolution capture?
Use the multi-resolution method when display scaling or native-resolution output matters. Use the simpler BufferedImage method when one predictable image size is sufficient.


