Library / SDK
NiiightmareXD/windows-capture avatar
NiiightmareXD/windows-capture

Windows Capture: a Rust screen capture library built on the Graphics Capture API

Fastest Windows Screen Capture Library For Rust And Python 🔥

519 stars82 forksRustMIT

At a glance

What is it?
Windows Capture wraps the Windows Graphics Capture API in a Rust crate with a handler trait, a settings builder for every capture option and a hardware-accelerated encoder, and the example in the readme records six seconds of video in about forty lines.
Who is it for?
Windows Capture fits a Rust developer who needs to capture a window or the screen on Windows for a recording tool, a screenshot feature or a bot, and who would rather not write against the raw WinRT graphics capture interfaces. It does not fit a cross-platform application, because the whole crate is a set of Windows bindings and there is nothing in it for macOS or Linux.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 18 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the library does, and what it is not

Windows Capture is a Rust and Python library for capturing the screen on Windows using the Graphics Capture API, and the readme states its use cases plainly: creating instructional videos, taking screenshots and recording gameplay. The pitch is efficiency, with the feature list claiming that it updates frames only when required, runs at high performance, is easy to use, uses the latest Windows Graphics Capture API, and supports the DXGI Desktop Duplication API as an alternative. Version 2.0.1 brought an enhanced hardware-accelerated video encoder with improved stability and monotonic audio timing, and new support for the DXGI Desktop Duplication API.

Two boundaries are worth stating before you look at the code. This README is for the Rust library, and the Python library lives in its own directory inside the same repository, so the two are versioned and documented separately even though the repository holds both. And the library is Windows only, which follows from it being a wrapper over a Windows API rather than a decision the author made. The licence is MIT, the crate is published on crates.io, the documentation is on docs.rs, and the primary language is Rust.

Installing it, and the Rust edition it targets

The dependency goes into your Cargo.toml.

toml
[dependencies]
windows-capture = "2.0.1"

Or you can let Cargo add it.

bash
cargo add windows-capture

The package manifest shows what the crate expects of the toolchain and the platform. The edition is 2024 and the resolver is 3, so this is a modern Cargo project rather than one that still supports older compilers. The documentation target is pinned to the Windows MSVC build, with both the default target and the target list set to x86_64-pc-windows-msvc, so the published docs are for 64-bit Windows and the crate has no other documentation build.

The capture handler, and how frames arrive

The usage example implements a trait called GraphicsCaptureApiHandler, and reading it tells you the whole shape of the API. The trait has an associated Flags type, used to pass values from the settings into the constructor, and an associated Error type. The new function receives a Context carrying those flags, the on_frame_arrived function is called every time a new frame is available and receives the frame plus a capture control handle, and an optional on_closed handler fires when the capture item, usually a window, is closed.

rust
impl GraphicsCaptureApiHandler for Capture {
    type Flags = (i32, i32);

    type Error = Box<dyn std::error::Error + Send + Sync>;

    fn new(ctx: Context<Self::Flags>) -> Result<Self, Self::Error> {
        let encoder = VideoEncoder::new(
            VideoSettingsBuilder::new(ctx.flags.0 as u32, ctx.flags.1 as u32),
            AudioSettingsBuilder::default().disabled(true),
            ContainerSettingsBuilder::default(),
            "video.mp4",
        )?;

The flags in the example are the width and height, and the constructor uses them to size the encoder. The comment on that constructor explains the alternative: if you did not want the size from the settings, you could use frame.width() and frame.height() inside on_frame_arrived, but then you would have to create the encoder there. So the library offers both, and the choice is about whether you want the encoder to exist before the first frame or to be built from the frame itself.

Writing frames out, and stopping the capture

The frame handler does the work, and the example in the readme shows the three things you can do with a frame. Send it to the video encoder, which is what the recording path does. Save a single frame to a file, with frame.save_as_image for a PNG. Or get the raw data with frame.buffer, which gives you full control over what happens next. The comments show those last two as alternatives to the encoder call rather than as separate steps.

rust
        // Send the frame to the video encoder
        self.encoder.as_mut().unwrap().send_frame(frame)?;

        // The frame has other uses too, for example, you can save a single frame
        // to a file, like this: frame.save_as_image("frame.png", ImageFormat::Png)?;
        // Or get the raw data like this so you have full control: let data = frame.buffer()?;

Stopping is done by finishing the encoder and then stopping the capture, and the example does it on a timer after six seconds. The capture control handle passed into the frame callback is what carries the stop method, so the handle and the frame travel together and the callback has everything it needs to end the session cleanly.

Picking what to capture, and the settings you can pass

Before any capture starts, the program opens a picker dialog so the user chooses a window or a screen, and the item that comes back carries the size you need for the settings. If the user cancels, the example prints a message and returns, which is why the code uses a let-else pattern on the picked item.

rust
    let item = GraphicsCapturePicker::pick_item().expect("Failed to pick item");

    let Some(item) = item else {
        println!("No item selected");
        return;
    };

    let size = item.size().expect("Failed to get item size");

The settings object then takes the item plus a series of option types, and every one of them has a Default variant, so you only set what you care about. There is CursorCaptureSettings for whether the cursor is drawn, DrawBorderSettings for the highlight border around a captured window, SecondaryWindowSettings to include secondary windows such as a dropdown, MinimumUpdateIntervalSettings for the minimum interval between eligible updates, DirtyRegionSettings for the dirty region, and ColorFormat for the desired format of the captured frame, which the example sets to Rgba8. The minimum update interval is the one worth understanding, because its own comment says it limits the update rate but does not guarantee a constant frame rate, and leaving it at the default leaves the Windows setting unchanged.

The Windows API surface underneath

The dependency list in the manifest is the clearest statement of what the library is doing, because it names the Windows feature sets it binds. The windows crate is pulled in at version 0.62.2 with a long feature list covering the Graphics Capture API itself, Direct3D 11 and DirectX, Dwm, Gdi, imaging and media core, media properties and transcoding, plus the WinRT Direct3D11 and Graphics Capture system features, and the windowing, HiDpi, shell and threading bits you would expect. Foundation, Foundation_Metadata and Storage round it out.

Three other dependencies do specific jobs. windows-future at 0.3.2 is the futures adapter for the async Windows APIs. parking_lot at 0.12.5 is there for a mutex optimisation, which matters in a capture path where contention shows up as dropped frames. rayon at 1.12.0 provides the multithreading, and thiserror at 2.0.18 handles the error types. The dev-dependencies are small, with clap for the command line example and ctrlc for interrupt handling.

The examples directory tells you what the library actually covers. There is a graphics_capture example, which is the one the readme walks through, a dxgi_duplication example for the newer Desktop Duplication path, a stream_capture example, and a cli example. Two of them are registered in the manifest with doc-scrape-examples disabled, which is a small detail that tells you the examples are meant to be read as examples rather than pulled into the documentation.

The Python side, and the examples as a guide

The Python library sits in the windows-capture-python directory of the same repository, and the readme points there explicitly rather than trying to document both in one page. That means the two bindings share the codebase but not the documentation, so if you are working in Python you should read that directory's own material and expect the version numbering and the API names to line up with the Rust side rather than being identical.

The examples are the best guide to what the library can do, and they are the reason to look at the repository rather than only the readme. The readme's own example is the simplest path, one that opens a picker, encodes six seconds of video to a file called video.mp4 and stops. The others show the parts that the simple example leaves out: dxgi_duplication covers the Desktop Duplication API, which the 2.0 release added as support, stream_capture covers capturing a stream rather than a single item, and cli is a command line front end with the clap and ctrlc dependencies behind it. The screenshots the readme points at show the same thing in pictures, a picker dialog, the settings, the preview and the resulting recording.

There is also a hosted option mentioned in the readme, Recall.ai, an API for desktop recording that records Zoom, Google Meet, Microsoft Teams and in-person meetings. It is presented as a sponsorship link rather than as part of the library, so it is worth knowing about if you want a service instead of a library, but nothing in the crate depends on it.

Where this library is the wrong choice

Three boundaries are clear. The first is the platform, and it is absolute: this captures Windows and only Windows, so a cross-platform application that needs screen capture on macOS and Linux has to use something else, or use something else on those platforms. The second is that the library is a capture library and not a recorder in the full sense. It gives you frames and an encoder, and assembling them into a recording pipeline with an overlay, an audio source, chapter markers or a streaming destination is work you do with the pieces it gives you. The third is that the audio path in the readme example is disabled, with the audio settings set to disabled, so the monotonic audio timing the 2.0 release highlights is a property of the new encoder rather than something the quick example exercises.

And there is a fourth point about what the claims mean. The fast label on the crate is the author's, and the feature list says frames update only when required, which is a property of the underlying Windows Graphics Capture API rather than something the library adds. The value of the wrapper is the ergonomics, the settings types, the frame handling and the encoder integration, all of which are real work you would otherwise write against the raw WinRT API. If your use is a single screenshot on demand, the overhead of a video pipeline is more than you need, and if your use is a high frame rate game recording on a machine where the encoder competes with the game for the GPU, the hardware-accelerated path and the dirty region and minimum interval settings are the levers you have, but they are Windows settings rather than knobs the library invents.

Editorial conclusion

Windows Capture fits a Rust developer who needs to capture a window or the screen on Windows for a recording tool, a screenshot feature or a bot, and who would rather not write against the raw WinRT graphics capture interfaces. It does not fit a cross-platform application, because the whole crate is a set of Windows bindings and there is nothing in it for macOS or Linux. It also does not fit someone who wants a finished recording pipeline, because the library hands you frames and an encoder and leaves the overlay, the audio source and the destination to you. Before you build, read the examples directory rather than only the readme, since the dxgi_duplication, stream_capture and cli examples cover ground the quick start does not, and check the minimum update interval setting, because its own documentation warns that it limits the update rate without guaranteeing a constant frame rate.

Frequently asked questions

How do I add windows-capture to a Rust project?

Add windows-capture = "2.0.1" to the dependencies section of your Cargo.toml, or run cargo add windows-capture. The crate targets the 2024 edition with resolver 3, and the published documentation is built for x86_64-pc-windows-msvc.

Which Windows capture APIs does the library support?

It uses the latest Windows Graphics Capture API and also supports the DXGI Desktop Duplication API, which was added in version 2.0.1. The windows crate dependency is enabled with the Graphics Capture, Direct3D 11, DirectX and WinRT graphics capture feature sets among others.

How do I choose what to capture and configure it?

GraphicsCapturePicker::pick_item opens a dialog to pick a window or screen, and the returned item carries the size you pass to Settings::new. The settings take option types with Default variants for cursor capture, draw border, secondary windows, minimum update interval, dirty region and colour format, so you only set what you need.

Is there a Python version of windows-capture?

Yes, and it lives in the windows-capture-python directory of the same repository. The readme you are reading documents the Rust library specifically and points to that directory for the Python binding.

Official sources

  1. Issues
  2. License: MIT
  3. NiiightmareXD/windows-capture on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/niiightmarexd-windows-capture.svg)](https://hysenlabs.com/projects/niiightmarexd-windows-capture)

Was this useful?