ScreenshotNeo

BlogScreenshots on your device

How to Save a Croppable PNG Screenshot to the Windows Desktop with Python

Capture part of your Windows screen with Python, crop it with Pillow, and save a PNG to the current user's Desktop.

By the ScreenshotNeo team1 October 20268 min read

Short answer: use PyAutoGUI to capture the visible screen as a Pillow image, call crop((left, upper, right, lower)), and save the result to Path.home() / 'Desktop' / 'filename.png'. The crop coordinates are pixel positions: the last two values are the ending coordinates, not width and height.

from pathlib import Path
import pyautogui

# Coordinates are pixels: left, upper, right, lower.
left, upper, right, lower = 100, 100, 700, 500
image = pyautogui.screenshot()
cropped = image.crop((left, upper, right, lower))

desktop = Path.home() / 'Desktop'
desktop.mkdir(parents=True, exist_ok=True)
output = desktop / 'cropped_screenshot.png'
cropped.save(output, format='PNG')
print(f'Saved: {output.resolve()}')

Install the dependencies in the same Python environment that will run the script:

python -m pip install pyautogui pillow

PyAutoGUI’s screenshot function returns an image and can save directly to a filename; its screenshot support requires Pillow. See the PyAutoGUI screenshot documentation.

1. Choose the capture method

Need Use Why
A simple screenshot and a crop decided in code PyAutoGUI + Pillow One call returns a Pillow image, so cropping and saving are straightforward.
A known rectangle, a specific monitor, or explicit region capture MSS MSS can grab a monitor or region directly and documents PNG output and Pillow conversion.
A one-off manual capture Windows Snipping Tool Microsoft documents selecting, editing, saving and sharing a snip. It is not a Python automation workflow.

Use coordinates from the capture library you choose. On a multi-monitor desktop, the coordinate space can include negative values or begin at a monitor origin other than (0, 0).

2. Install Python packages on Windows

  1. Install Python and make sure python --version works in PowerShell or Command Prompt.
  2. Create a project folder and, optionally, a virtual environment.
  3. Install PyAutoGUI and Pillow:
python -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install pyautogui pillow

Using python -m pip ties installation to the interpreter that runs the script, which avoids the common case where a package was installed for a different Python installation.

3. Capture the full screen, then crop it

This pattern is useful when you want to inspect the full screenshot first or calculate the crop after another step. Pillow uses a four-value box:

(left, upper, right, lower)

The origin is the upper-left corner. The right and lower values mark the opposite edge. If you have a rectangle expressed as (left, top, width, height), convert it before calling crop:

right = left + width
lower = top + height
cropped = image.crop((left, top, right, lower))

A complete script with validation and useful output:

from pathlib import Path
import pyautogui

# Rectangle in left, top, width, height form.
left, top, width, height = 100, 100, 600, 400
if width <= 0 or height <= 0:
    raise ValueError('width and height must be positive')

right = left + width
lower = top + height

image = pyautogui.screenshot()
print(f'Full screenshot dimensions: {image.size[0]}x{image.size[1]}')

# Keep the requested box inside the captured image.
image_width, image_height = image.size
if left < 0 or top < 0 or right > image_width or lower > image_height:
    raise ValueError(
        f'Crop {(left, top, right, lower)} is outside '
        f'the captured image {(image_width, image_height)}'
    )

cropped = image.crop((left, top, right, lower))
desktop = Path.home() / 'Desktop'
desktop.mkdir(parents=True, exist_ok=True)
output = desktop / 'cropped_screenshot.png'
cropped.save(output, 'PNG')
print(f'Crop dimensions: {cropped.size[0]}x{cropped.size[1]}')
print(f'Saved: {output.resolve()}')

The parent directory check is harmless when Desktop already exists and helps when a profile has an unusual setup. Windows profiles may redirect Desktop to a cloud-synced or organization-managed location. If the file is not where you expect, use the printed resolved path or set desktop to your actual Desktop folder.

4. Capture only a region with MSS

If the rectangle is known before capture, MSS avoids taking a full-screen image first. Its documentation covers monitor selection, region capture, PNG saving and conversion to Pillow for later image processing. Install it with:

python -m pip install mss pillow

Direct region capture and PNG output:

from pathlib import Path
from mss import mss

left, top, width, height = 100, 100, 600, 400
if width <= 0 or height <= 0:
    raise ValueError('width and height must be positive')

region = {'left': left, 'top': top, 'width': width, 'height': height}
desktop = Path.home() / 'Desktop'
desktop.mkdir(parents=True, exist_ok=True)
output = desktop / 'mss_region.png'

with mss() as capture:
    capture_img = capture.grab(region)
    capture.tools.to_png(capture_img.rgb, capture_img.size, output=str(output))

print(f'Saved: {output.resolve()}')

To process the MSS result with Pillow, convert it first:

from pathlib import Path
from mss import mss
from PIL import Image

region = {'left': 100, 'top': 100, 'width': 600, 'height': 400}
desktop = Path.home() / 'Desktop'
desktop.mkdir(parents=True, exist_ok=True)
output = desktop / 'mss_processed.png'

with mss() as capture:
    shot = capture.grab(region)
    image = Image.frombytes('RGB', shot.size, shot.rgb)
    # Further Pillow operations can go here.
    image.save(output, 'PNG')

print(f'Saved: {output.resolve()}')

For another monitor, use its origin when constructing the region. MSS exposes monitor information through its monitor list; anchor the rectangle to the selected monitor rather than assuming the primary display starts at zero. A monitor positioned left of the primary display can have negative screen coordinates.

5. Make the crop interactively selectable

The examples above use known coordinates. If a person should choose the rectangle with the mouse, capture the pointer positions and convert them to a normalized box before cropping. The exact interaction layer depends on the GUI toolkit you choose; the important Pillow rule remains the same:

left = min(start_x, end_x)
right = max(start_x, end_x)
upper = min(start_y, end_y)
lower = max(start_y, end_y)
cropped = image.crop((left, upper, right, lower))

Normalize the two corners so dragging in any direction works. Reject a zero-width or zero-height selection, and ensure the pointer coordinates and screenshot coordinates use the same scaling and monitor space.

6. PNG options and file handling

PNG is lossless, so it preserves sharp text and UI edges. Pillow accepts a path object and lets you specify the format explicitly:

cropped.save(output, format='PNG', optimize=True)

Use a unique filename when a script runs repeatedly:

from datetime import datetime
output = desktop / f'screenshot-{datetime.now():%Y%m%d-%H%M%S}.png'

Check the resulting dimensions before handing the file to another process:

with Image.open(output) as saved:
    print(saved.format, saved.size, saved.mode)

7. Troubleshooting

Symptom Likely cause Fix
ModuleNotFoundError: pyautogui or PIL The package is missing from the active interpreter. Activate the correct virtual environment and run python -m pip install pyautogui pillow.
The crop is empty or has unexpected dimensions The tuple was supplied as (left, top, width, height). Convert to (left, top, left + width, top + height).
ValueError for an invalid crop Coordinates are reversed, zero-sized, negative, or outside the image. Normalize both corners and compare the box with image.size.
The wrong monitor was captured Coordinates were assumed to start at zero. Inspect monitor origins and use the selected monitor’s left and top offsets.
The image is saved but cannot be found Desktop is redirected or a relative path was used. Print output.resolve() and check the displayed location; set an explicit Desktop path if needed.
The screenshot does not show a minimized window These libraries capture visible screen pixels. Bring the target content onto the visible desktop before capture.
A protected video surface is black Some applications restrict screen capture. Do not assume ordinary desktop capture can bypass application-specific protection.

8. Performance, reliability and repeatability

  • Capture less when you can: MSS region capture avoids processing pixels outside the requested rectangle.
  • Use full-screen capture when the crop is dynamic: it gives your code a stable image to inspect and crop later.
  • Keep coordinate spaces consistent: display scaling, multiple monitors and remote-desktop sessions can change the relationship between logical pointer coordinates and image pixels. Print the captured dimensions and inspect a sample output.
  • Create output directories deliberately: use Path.home() rather than embedding another person’s C:\Users\... path.
  • Verify the artifact: check that the file exists, can be opened, and has the expected dimensions before reporting success.
  • Do not promise invisible or protected captures: the documented workflows capture visible monitors or regions, not every application surface.

9. Or skip the browser setup

If you need screenshots of web pages rather than pixels on your Windows desktop, ScreenshotNeo returns a PNG, JPEG, WebP or PDF from one GET request. Its browser capture can accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups and chat widgets before the shot. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

Read the ScreenshotNeo API documentation for the complete option list, including full-page and element capture, device presets, custom CSS and JavaScript, waits, blocking rules, authentication headers and cookies, caching, signed links, asynchronous jobs, bulk capture and PDFs.

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(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

The MCP server also provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan.

Create a free ScreenshotNeo account to try the API without a card.

10. FAQ

Should I use PyAutoGUI or MSS?

Use PyAutoGUI for the shortest full-screen-to-Pillow workflow. Use MSS when you know the region in advance, need explicit monitor selection, or want direct region capture.

Are crop coordinates width and height?

No. Pillow expects (left, upper, right, lower). Add width to left and height to top when converting from a size-based rectangle.

Where is the Windows Desktop path?

Path.home() / 'Desktop' is the portable starting point. Print the resolved path because Windows profiles can redirect Desktop.

Can this capture a minimized window?

No. These workflows capture visible screen or monitor pixels. A minimized or protected surface may not appear in the result.

Can I save JPEG instead?

Yes, Pillow can save other formats, but PNG is usually preferable for text and interface screenshots because it is lossless.