Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

DXcam

Fast Python Screen Capture for Windows - Updated 2026

import dxcam

with dxcam.create() as camera:
    frame = camera.grab()

Live API Docs: https://ra1nty.github.io/DXcam/

Introduction

DXcam is a high-performance python screenshot and capture library for Windows based on the Desktop Duplication API. It is designed for low-latency, high-FPS capture pipelines (including full-screen Direct3D applications).

Compared with common Python alternatives, DXcam focuses on:

  • Higher capture throughput (240+fps on 1080p)
  • Stable capture for full-screen exclusive Direct3D apps
  • Better FPS pacing for continuous video capture
  • Support DXGI / Windows Graphics Capture dual backend
  • Seamless integration for AI Agent / Computer Vision use cases.

Installation

From PyPI (pip)

Minimal install:

pip install dxcam

Full feature: (includes OpenCV-based color conversion, WinRT capture backend support:):

pip install "dxcam[cv2,winrt]"

Notes:

  • Official Windows wheels are built for CPython 3.10 to 3.14.
  • Binary wheels include the Cython kernels used by processor backends.

From source

Please refer to CONTRIBUTING.

Contributing / Dev

Contributions are welcome! Development setup and contributor workflow are documented in CONTRIBUTING.md.

Usage

Each output (monitor) is associated with one DXCamera instance.

import dxcam
camera = dxcam.create()  # primary output on device 0

To specify backends:

camera = dxcam.create(
    backend="dxgi", # default Desktop Duplication backend
    processor_backend="cv2" # default OpenCV processor
)

Note:

  • Version 0.4 uses a fixed three-slot frame buffer; max_buffer_len has been removed.
  • Device discovery happens on the first create(), device_info(), or output_info() call.
  • Upgrading from 0.3? See the 0.4 migration guide.

Screenshot

frame = camera.grab()

grab() returns a numpy.ndarray. In one-shot mode it returns None if no new frame is available; camera.grab(new_frame_only=False) can reuse the last cached frame. During threaded capture, it reads the latest published frame and ignores new_frame_only.

Use camera.grab_into(dst) to reuse caller-managed memory.

To capture a region:

left, top = (1920 - 640) // 2, (1080 - 640) // 2
right, bottom = left + 640, top + 640
frame = camera.grab(region=(left, top, right, bottom)) # numpy.ndarray of size (640x640x3) -> (HXWXC)

Screen Capture

camera.start(region=(left, top, right, bottom), target_fps=60)
camera.is_capturing  # True
# ...
camera.stop()
camera.is_capturing  # False

Consume the Screen Capture Data

for _ in range(1000):
    frame = camera.get_latest_frame()  # waits for the first available frame

The capture thread publishes into a latest-only frame buffer. Once a frame is available, reads return immediately and can return the same timestamp repeatedly. Consumers control their own pacing; compare timestamps when you need only fresh frames. target_fps controls the producer, not the frequency of consumer reads.

Useful variants:

  • camera.get_latest_frame(with_timestamp=True) -> (frame, frame_timestamp) -> return frame timestamp
  • camera.get_latest_frame_into(dst) -> write latest frame into caller-provided array

When start() capture is running, calling grab() reads from the in-memory frame buffer instead of directly polling the capture backend.

Safely Releasing Resources

release() stops capture, frees buffers, and releases capture resources. After release(), the same instance cannot be reused. In-flight readers retain their staging surfaces until readout completes, including across stop or output recovery.

camera = dxcam.create(output_idx=0, output_color="BGR")
camera.release()
# camera.start()  # raises RuntimeError

Equivalently you can use context manager:

with dxcam.create() as camera:
    frame = camera.grab()
# resource released automatically

Full API Docs: https://ra1nty.github.io/DXcam/

Advanced Usage and Remarks

Multiple monitors / GPUs

cam1 = dxcam.create(device_idx=0, output_idx=0)
cam2 = dxcam.create(device_idx=0, output_idx=1)
cam3 = dxcam.create(device_idx=1, output_idx=1)

img1 = cam1.grab()
img2 = cam2.grab()
img3 = cam3.grab()

Inspect available devices/outputs:

>>> import dxcam
>>> print(dxcam.device_info())
'Device[0]:<Device Name:NVIDIA GeForce RTX 3090 Dedicated VRAM:24348Mb VendorId:4318>\n'
>>> print(dxcam.output_info())
'Device[0] Output[0]: Res:(1920, 1080) Rot:0 Primary:True\nDevice[0] Output[1]: Res:(1920, 1080) Rot:0 Primary:False\n'

Output Format

Set output color mode when creating the camera:

dxcam.create(output_color="BGRA")

Supported modes: "RGB", "RGBA", "BGR", "BGRA", "GRAY".

Notes:

  • Data is returned as numpy.ndarray.
  • BGRA does not require OpenCV and is the leanest dependency path.
  • RGB, BGR, RGBA, GRAY require conversion (cv2, cython, or compiled numpy backend).

Frame Buffer

DXcam uses a fixed three-slot latest-only frame buffer in-memory. Readers consume the newest published frame. A surface being read is never overwritten; if no safe write slot is available, capture skips that cycle. Older surfaces are released only after their readers finish.

camera = dxcam.create()

Target FPS

DXcam uses high-resolution pacing with drift correction to run near target_fps.

camera.start(target_fps=120)  # default to 60, greater than 120 is resource heavy

On Python 3.11+, DXcam relies on Windows high-resolution timer behavior used by time.sleep(). On older versions, DXcam uses WinAPI waitable timers directly.

Frame Timestamp

Read the most recent frame timestamp (seconds):

camera.start(target_fps=60)
frame, ts = camera.get_latest_frame(with_timestamp=True)
camera.stop()

For backend="dxgi", this value comes from DXGI_OUTDUPL_FRAME_INFO.LastPresentTime. For backend="winrt", this value is derived from WinRT SystemRelativeTime.

Video Mode

With video_mode=True, DXcam continues publishing at target FPS, reusing the previous frame when no new frame is rendered.

import cv2
import dxcam
import time

target_fps = 30
camera = dxcam.create(output_color="BGR")
camera.start(target_fps=target_fps, video_mode=True)

writer = cv2.VideoWriter(
    "video.mp4", cv2.VideoWriter_fourcc(*"mp4v"), target_fps,
    (camera.width, camera.height),
)
try:
    next_frame = time.perf_counter()
    for _ in range(600):
        time.sleep(max(0, next_frame - time.perf_counter()))
        next_frame = time.perf_counter() + 1 / target_fps
        frame = camera.get_latest_frame()
        if frame is not None:
            writer.write(frame)
finally:
    camera.release()
    writer.release()

Latest-frame reads return immediately once a frame exists. Pace the consumer as above to avoid filling the video with repeated reads as fast as Python can run.

Capture Backend

DXcam supports two capture backends:

  • dxgi (default): Desktop Duplication API path with broad compatibility.
  • winrt: Windows Graphics Capture path.

Use it like this:

camera = dxcam.create(backend="dxgi")
camera = dxcam.create(backend="winrt")

Guideline:

  • If you need cursor rendering, use winrt.
  • Start with dxgi for most workloads, especially one-shot grab.
  • Try winrt if it performs better on your machine or fits your app constraints.

Processor Backend

DXcam capture backends (dxgi/winrt) acquire raw BGRA frame. The processor backend then handles post-processing:

  • optional rotation/cropping preparation
  • color conversion to your output_color

Recommended backend choice:

  • OpenCV installed: use cv2 (default)
  • No OpenCV installed: use numpy/cython

Use it like this:

camera = dxcam.create(processor_backend="cv2")
camera = dxcam.create(processor_backend="cython")
camera = dxcam.create(processor_backend="numpy")

Official Windows wheels already include the compiled Cython processor kernels.

Only for source installs:

set DXCAM_BUILD_CYTHON=1
pip install -e .[cython] --no-build-isolation

If processor_backend="numpy" is selected but compiled kernels are unavailable, DXcam logs a warning and falls back to cv2 behavior. In that fallback path, install OpenCV for non-BGRA output modes.

If processor_backend="cython" is selected but compiled kernels are unavailable, DXcam raises a runtime error because that backend is explicitly the direct Cython path.

Benchmarks

See the 0.4 development comparison against PyPI 0.3.0 for measured fresh-frame throughput, frame age, CPU use, and reproducible steps.

When using a similar logic (only capture newly rendered frames) running on a 240fps output, DXCam, python-mss, D3DShot benchmarked as follow:

DXcam python-mss D3DShot
Average FPS 239.19 🏁 75.87 118.36
Std Dev 1.25 0.5447 0.3224

The benchmark is across 5 runs, with a light-moderate usage on my PC (5900X + 3090; Chrome ~30tabs, VS Code opened, etc.), I used the Blur Buster UFO test to constantly render 240 fps on my monitor. DXcam captured almost every frame rendered. You will see some benchmarks online claiming 1000+fps capture while most of them is busy-spinning a for loop on a staled frame (no new frame rendered on screen in test scenario).

For Targeting FPS:

(Target)\(mean,std) DXcam (4k) python-mss D3DShot (1080p)
60fps 59.99, 0.04 🏁 N/A 47.11, 1.33
30fps 30.00, 0.00 🏁 N/A 21.24, 0.17

Work Referenced

OBS Studio - implementation ideas and references.

D3DShot : DXcam borrowed some ctypes header from the no-longer maintained D3DShot.

Release files for dxcam 0.4.0.dev2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dxcam 0.4.0.dev2
File Size Uploaded
dxcam-0.4.0.dev2.tar.gz 416.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for dxcam 0.4.0.dev2
File
dxcam-0.4.0.dev2-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details
dxcam-0.4.0.dev2-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
dxcam-0.4.0.dev2-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
dxcam-0.4.0.dev2-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
dxcam-0.4.0.dev2-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details

Total release size: 3.9 MB

Release files / dxcam-0.4.0.dev2.tar.gz

Download URL dxcam-0.4.0.dev2.tar.gz
Size 416.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d4b153dd93f75d779d079bf69299a7d0ed374e383349f08a26572d88ff3bc6be
BLAKE2b-256 checksum
How to use checksums
a40e67baebf235247597473c9cb354f7f029ad49fff2ff0551a46d13e83a7279
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / dxcam-0.4.0.dev2-cp314-cp314-win_amd64.whl

Download URL dxcam-0.4.0.dev2-cp314-cp314-win_amd64.whl
Size 699.2 kB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
3fadc424f2380a244100da15080b6baa0ca9531f2f0904c09b14ee08f6560ca0
BLAKE2b-256 checksum
How to use checksums
19fd4d0b8a77fb25fd6aad18778932bb2796df48f0d48c8aab62672256712807
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / dxcam-0.4.0.dev2-cp313-cp313-win_amd64.whl

Download URL dxcam-0.4.0.dev2-cp313-cp313-win_amd64.whl
Size 695.8 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
7978a575112335e68fb7eebb9097b11de3c4ffa2d9ea198a742b82190483c3bf
BLAKE2b-256 checksum
How to use checksums
bfa4f906d85554d8b3fd3bf6855f7923f69d3f79317708b276edc5dd640488ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / dxcam-0.4.0.dev2-cp312-cp312-win_amd64.whl

Download URL dxcam-0.4.0.dev2-cp312-cp312-win_amd64.whl
Size 696.3 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
23d7ea5cd2c075e2c9097713632b25657cf22e30a049bc0dadc2bcaa86f70305
BLAKE2b-256 checksum
How to use checksums
5db4a41077ddfdca994515173a82d6734b7a7632ab12c9f892bdc1a082ee7f20
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / dxcam-0.4.0.dev2-cp311-cp311-win_amd64.whl

Download URL dxcam-0.4.0.dev2-cp311-cp311-win_amd64.whl
Size 693.0 kB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
4e5655e280d79b50fb589fd0576050e056272139db858a3c20acb3e30e506c25
BLAKE2b-256 checksum
How to use checksums
6de52a33a9257486a5b05531182bc25425a5fa0bbd10807a37c539972f46d5cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / dxcam-0.4.0.dev2-cp310-cp310-win_amd64.whl

Download URL dxcam-0.4.0.dev2-cp310-cp310-win_amd64.whl
Size 693.1 kB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
3d2fb800299838cc6b70261ccbc612ac2bda6d8008281b5af1b1ca4a823f19b9
BLAKE2b-256 checksum
How to use checksums
fbde91b06d77e1ab27cc86a619e81056531a73c7d0f25492923e467ce26b386b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page