BlogScreenshots on your device
How to Capture a Region of the Screen with CopyFromScreen in C#
Capture and save any rectangular screen area in C# with Graphics.CopyFromScreen, including DPI, multi-monitor, errors, and alternatives.
Use Graphics.CopyFromScreen to copy a rectangular group of screen pixels into a Bitmap, then save that bitmap as PNG, JPEG, or another supported format. The source point is the rectangle’s upper-left screen coordinate, the destination point is usually (0, 0) in the bitmap, and Size supplies the width and height. Microsoft defines the method as performing a bit-block transfer of pixel color data from the screen to a Graphics drawing surface. See the CopyFromScreen API reference.
Minimal working example
using System;
using System.Drawing;
class Program
{
static void Main()
{
const int x = 100;
const int y = 80;
const int width = 400;
const int height = 250;
using var image = CaptureRegion(x, y, width, height);
image.Save("capture.png");
}
static Bitmap CaptureRegion(int x, int y, int width, int height)
{
if (width <= 0)
throw new ArgumentOutOfRangeException(nameof(width));
if (height <= 0)
throw new ArgumentOutOfRangeException(nameof(height));
var bitmap = new Bitmap(width, height);
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.CopyFromScreen(
sourceX: x,
sourceY: y,
destinationX: 0,
destinationY: 0,
blockRegionSize: new Size(width, height));
}
return bitmap;
}
}
The example captures a 400-by-250 rectangle beginning at screen coordinate (100, 80). The returned bitmap belongs to the caller, so the caller disposes it. The Graphics object is disposed immediately after the copy.
How the coordinates and size work
| Argument | Meaning |
|---|---|
sourceX, sourceY |
Upper-left pixel of the source rectangle on the screen. |
destinationX, destinationY |
Upper-left position on the destination graphics surface. Use 0, 0 when filling a new bitmap. |
blockRegionSize |
Number of pixels to copy: Width by Height. |
The point-and-size overload expresses the same operation:
graphics.CopyFromScreen(
new Point(sourceX, sourceY),
new Point(0, 0),
new Size(width, height));
There is also an overload accepting CopyPixelOperation. Its value controls how source and destination colors are combined. Use the ordinary overload for a normal screenshot. CopyPixelOperation.CaptureBlt is documented to include layered windows above the target window, although protected surfaces and particular desktop configurations can still prevent capture.
Save as PNG, JPEG, or WebP-compatible output
System.Drawing can save common Windows image formats through ImageFormat:
using System.Drawing.Imaging;
using var image = CaptureRegion(100, 80, 400, 250);
image.Save("capture.png", ImageFormat.Png);
image.Save("capture.jpg", ImageFormat.Jpeg);
PNG preserves sharp text and transparency. JPEG is smaller for photographic content but introduces lossy compression. Choose an encoder and quality setting when you need explicit JPEG quality:
using System.Drawing.Imaging;
using var image = CaptureRegion(100, 80, 400, 250);
var codec = ImageCodecInfo.GetImageEncoders()
.First(c => c.FormatID == ImageFormat.Jpeg.Guid);
using var parameters = new EncoderParameters(1);
parameters.Param[0] = new EncoderParameter(Encoder.Quality, 85L);
image.Save("capture.jpg", codec, parameters);
Add using System.Linq; for the encoder example. WebP encoding is not supplied by the basic System.Drawing API; use an image library that supports it if WebP is required.
Put the capture code in a reusable method
using System;
using System.Drawing;
public static class ScreenCapture
{
public static Bitmap Region(Rectangle rectangle)
{
if (rectangle.Width <= 0 || rectangle.Height <= 0)
throw new ArgumentException("The rectangle must have positive dimensions.", nameof(rectangle));
var bitmap = new Bitmap(rectangle.Width, rectangle.Height);
try
{
using var graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(
rectangle.Left,
rectangle.Top,
0,
0,
rectangle.Size);
return bitmap;
}
catch
{
bitmap.Dispose();
throw;
}
}
}
// Example:
using var shot = ScreenCapture.Region(new Rectangle(100, 80, 400, 250));
shot.Save("region.png");
The cleanup in the catch prevents a bitmap leak if the graphics operation fails before ownership is returned.
Project and platform requirements
With .NET 6 and later, System.Drawing.Common is supported only on Windows. A non-Windows target produces platform analyzer warnings and may fail at runtime. Enable Windows targeting in a Windows project and keep this capture path behind a Windows-specific boundary:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
</Project>
For cross-platform image processing, Microsoft lists libraries such as SkiaSharp and ImageSharp, but those libraries do not themselves provide this screen acquisition operation. If you need display or application-window frames, investigate the separate Windows.Graphics.Capture API, which has a picker-oriented workflow and supports snapshots or streams.
DPI, multiple monitors, and coordinate edge cases
- DPI scaling: UI frameworks may expose device-independent coordinates while
CopyFromScreenconsumes physical screen coordinates. Configure and verify the process DPI-awareness setting for the application. Microsoft documentsGetDpiForWindowas a way to query a desktop window’s DPI. - Negative coordinates: A monitor positioned left of or above the primary display can give the virtual desktop negative X or Y coordinates. Do not clamp coordinates to zero unless your product intentionally restricts capture to the primary monitor.
- Cross-monitor rectangles: A rectangle can span displays with different scaling factors. Verify the result on the actual monitor arrangement and DPI-awareness mode; there is no universal mapping for every UI framework.
- Changing display layouts: Store a fresh rectangle before each capture if displays can be connected, disconnected, or rearranged.
- Out-of-bounds areas: Validate the requested rectangle against the current virtual screen. Behavior at uncovered or invalid coordinates is environment-dependent, so reject impossible requests when predictable output matters.
- Protected content: DRM video, secure desktops, elevated prompts, and some remote-session surfaces may be unavailable or black even when ordinary windows capture correctly.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
Win32Exception |
The screen transfer failed. | Check that the dimensions are positive, the coordinates describe a currently available desktop area, and the process is running in a supported Windows desktop session. Log the requested rectangle and retry only when the failure is transient. |
| Platform warning or runtime failure on Linux/macOS | System.Drawing.Common is Windows-only from .NET 6 onward. |
Run this implementation on Windows or choose a platform-specific capture API for the target operating system. |
| Black or incomplete image | Protected content, layered-window behavior, minimized/virtualized content, or an unavailable desktop surface. | Try the overload with CopyPixelOperation.CaptureBlt for layered windows. Do not assume it can bypass protected content; use an appropriate capture API or change the capture target. |
| Image is shifted or the wrong size | Source and destination origins or DPI coordinate systems were mixed. | Use destination (0, 0), verify the rectangle in physical pixels, and inspect the process and monitor DPI settings. |
| Out-of-memory or slow captures | Large bitmaps retained too long or many captures performed concurrently. | Dispose each bitmap promptly, reduce the region, avoid unnecessary copies, and bound concurrency. |
| File cannot be overwritten | A previous Bitmap or stream still owns the file. |
Dispose the image and stream before opening the same path again; write to a temporary path and move it after a successful save. |
Performance and reliability checklist
- Capture only the required rectangle. Memory use is approximately proportional to width × height × bytes per pixel.
- Reuse a capture schedule rather than starting unbounded worker tasks. A bounded queue prevents memory growth during bursts.
- Save asynchronously at the application level if disk I/O must not block a UI thread, while ensuring the bitmap remains alive until encoding completes.
- Keep capture and encoding errors separate in logs so a successful copy is not mistaken for a successful file write.
- Record the rectangle, display arrangement, DPI-awareness mode, output format, and exception details for reproducibility.
- Do not promise a universal frame rate or latency: the dossier sources provide no benchmark, and results vary with resolution, desktop composition, encoding, and hardware.
Or skip the browser setup
ScreenshotNeo is for website captures rather than a local desktop rectangle. One GET request returns a PNG, JPEG, WebP, or PDF, and the API accepts options for full-page captures, CSS-element selection, viewport and device settings, retina scale, custom CSS and JavaScript, waits, blocking rules, headers, cookies, user agents, geolocation, caching, signed links, asynchronous jobs, bulk capture, and more. See the ScreenshotNeo API 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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing result. An MCP server lets Claude, Cursor, and other MCP clients take screenshots. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Can CopyFromScreen capture a browser tab without capturing the rest of the desktop?
It copies screen pixels, so pass the browser window’s screen rectangle. For a web page independent of an interactive desktop, use a browser automation or website screenshot service instead.
Does the method capture the mouse pointer?
The API copies pixel color data from the screen. The pointer is not guaranteed to appear; use a cursor-specific implementation when pointer visualization is required.
Should I use CopyFromScreen or Windows.Graphics.Capture?
Use CopyFromScreen for a straightforward rectangular bitmap on Windows. Investigate Windows.Graphics.Capture when you need picker-based window/display selection, repeated frames, or a capture stream.
Is this suitable for server-side screenshot generation?
Only when the process has access to the intended interactive Windows desktop. Headless or web-server workloads generally need a browser capture workflow or an API designed for website screenshots.


