65

I am looking for a way to take a screenshot of the entire screen from the command line. Operating system is Windows. Something like this:

C:\>screenshot.exe screen1.png
6
  • 1
    Why would you want to do something like that ? Apart from the obvious deficiency (it being able to take screenshots only of the command line you're currently working on), what's wrong with the "regular" solutions for such purpose ?
    – Rook
    Nov 26, 2009 at 15:53
  • 10
    Why would it be restricted to take a picture of the cmd line only? I think the question goes more along the lines of automation.
    – Gerd Klima
    Nov 26, 2009 at 15:57
  • Well, in the moment he wants to take a screenshot, he has to press enter to give the command, doesn't he ? He could of course use a script to time-activate it, but then he's really reinventing hot water.
    – Rook
    Nov 26, 2009 at 16:00
  • I would like to write a script that opens eml file in Thunderbird, takes a screen shot, opens another file, takes another screen shoot... For all files in a folder. I want to execute screen shot tool from the command line, so it could be automated. Just to be clear, I do not want to take a screen shot of command line, but of the entire screen. In fact, I have already written the script, I am just looking for more options to take the screen shot. Nov 27, 2009 at 11:10
  • 3
    @Idigias: first of all, the screen is larger than a CMD box, but secondly : when a script launches a GUI tool, that GUI tool takes focus. So, your "obvious deficiency" is not obvious, and no deficiency either. Have you ever worked with command line ?
    – tvCa
    Apr 13, 2015 at 9:49

13 Answers 13

30

Download imagemagick. Many command line image manipulation tools are included. import allows you to capture some or all of a screen and save the image to a file. For example, to save the entire screen as a jpeg:

import -window root screen.jpeg

If you want to use the mouse to click inside a window or select a screen region & save a a png, just use:

import box.png
6
  • 15
    This doesn't seem to work on Windows. I get an X server error about file not found. Apr 5, 2011 at 18:14
  • 2
    @BinaryPhile Yea I think this would only work with an X server running on Cygwin. May 12, 2014 at 8:42
  • It still doesn't work for me. I get a screenshot, but only the X applications show up (as expected). Oct 9, 2015 at 13:11
  • hm, ImageMagick is 25 Mb, and does TON of cool stuff. screenCapture.bat, below, is 9 Kb, and simply does exactly what the OP requested. At .04% the size of ImageMagick.
    – johny why
    Apr 12, 2016 at 0:59
  • 1
    @johnywhy solution with bat file below just 9kb? Does that include the C# compiler and .NET framework called by the script? ImageMagick might be pale compared to compiling that script for each screenshot.
    – Roland
    Dec 9, 2021 at 14:34
49

This question's already been answered, but I thought I'd throw this in as well. NirCmd (freeware, sadly, not open source) can take screenshots from the command line, in conjunction with the numerous other functions it can do.

Running this from the command line either in nircmd.exe's directory or if you copied it to your system32 folder:

nircmd.exe savescreenshot screen1.png

does what you want. You can also delay it like this:

nircmd.exe cmdwait 2000 savescreenshot screen1.png

That will wait 2000 milliseconds (2 seconds), and then capture and save the screenshot.

3
  • Nircmd does not support multiple screens. It will capture the primary screen only. May 19, 2015 at 8:58
  • 1
    Looks like the recent versions can do multiple screens. savescreenshotfull [filename]
    – w32sh
    Feb 26, 2016 at 10:47
  • I couldn't find the download link for nircmd2 initially. Google search didn't show anything. For users looking to download nircmd2, the download link is located at the very bottom of the page nirsoft.net/utils/nircmd.html. You can directly use this download link: nirsoft.net/utils/nircmd.zip
    – alpha_989
    Feb 1, 2018 at 19:46
41

it can be done without external tools (you just need installed .net framework ,which is installed by default on everything from vista and above) - screenCapture.bat. It is a selfcompiled C# program and you can save the output in few formats and capture only the active window or the whole screen:

screenCapture- captures the screen or the active window and saves it to a file
Usage:
screenCapture  filename.format [WindowTitle]

filename - the file where the screen capture will be saved
format - Bmp,Emf,Exif,Gif,Icon,Jpeg,Png,Tiff and are supported - default is bmp
WindowTitle - instead of capturing the whole screen will capture the only a window with the given title if there's such

Examples:

call screenCapture notepad.jpg "Notepad"
call screenCapture screen.png
11
  • 3
    Definitely the best solution. Super-tiny 9K! That's 0.04% the size of ImageMagick (25 Mb). It uses built-in Windows functionality. Tinier than all other solutions on this page. Best!
    – johny why
    Apr 12, 2016 at 1:01
  • 1
    One thing that I noticed about this solution is that there are specific things that it does not capture. For example, some applications are attaching themselves and creating huds on other applications that are not rendered in the captured image. In those extreme cases I found that MiniCap works. In most cases though, this solution right here is the fastest and most uncomplicated that you can find.
    – F1234k
    Sep 5, 2016 at 22:40
  • Hi @npocmaka, I have two monitor that desktop is extended on them. I want to take screenshot of desktop of the second monitor. But your program just take screenshots from primary desktop. Any trick?
    – mini
    Mar 4, 2019 at 14:02
  • 1
    Doesn't seem to work for me, it always just outputs a black image regardless of the extension.
    – bparker
    Aug 5, 2020 at 22:16
  • 2
    This BAT/C# script works great. I would still prefer to build the EXE, and call that from the BAT, but this works. And I learned some more C# and BAT commands. +1
    – Roland
    Dec 9, 2021 at 15:10
13

Other suggestions are fine -- you could also try MiniCap, which is free and has some other features like flexible file naming and some different capture modes: http://www.donationcoder.com/Software/Mouser/MiniCap/index.html

(disclaimer: I'm the author of MiniCap).

2
  • 1
    Then you must also be the author of Screenshot Captor. I found it a better solution for my needs. Thank you!
    – jon3laze
    Aug 24, 2012 at 20:50
  • 1
    It is free for personal use only. For commercial use, a license for Screenshot Captor is needed. May 19, 2015 at 8:59
13

Try IrfanView.

You can run it via command-line. You can specify which window to capture – such as whole window or just the current/active window – and you can also do some basic editing such as sharpening, cropping or resizing the images.

Here are the command line options, particularly interesting is

i_view32 /capture=0 /convert=wholescreen.png
1
  • I've using IrfanView for years, never know it could do this. Thanks for sharing. Nov 27, 2019 at 8:37
9

Screenshot-cmd takes a screenshot of a desktop or any window selected by window title. It is also possible to select rectangle to capture. The result is stored as a png file. (last update in 2011)


OPTIONS:
    -wt WINDOW_TITLE
            Select window with this title.
            Title must not contain space (" ").
    -wh WINDOW_HANDLE
            Select window by it's handle
            (representad as hex string - f.e. "0012079E") 
    -rc LEFT TOP RIGHT BOTTOM
            Crop source. If no WINDOW_TITLE is provided
            (0,0) is left top corner of desktop,
            else if WINDOW_TITLE maches a desktop window
            (0,0) is it's top left corner.
    -o FILENAME
            Output file name, if none, the image will be saved
            as "screenshot.png" in the current working directory.
    -h
            Shows this help info.

Inspired by: http://blog.mozilla.com/ted/2009/02/05/command-line-screenshot-tool-for-windows/

1
  • 1
    This is open source, BSD license. Very simple and small - for me these are advantages.
    – Jarekczek
    Jan 24, 2015 at 12:06
7

You can try the boxcutter tool:

usage: boxcutter [OPTIONS] [OUTPUT_FILENAME]

Saves a bitmap screenshot to 'OUTPUT_FILENAME' if given.  Otherwise, 
screenshot is stored on clipboard by default.

OPTIONS
  -c, --coords X1,Y1,X2,Y2    capture the rectange (X1,Y1)-(X2,Y2)
  -f, --fullscreen            fullscreen screenshot
  -v, --version               display version information
  -h, --help                  display help message
2
  • This one supports multiple monitors but adds some extra black area in version 1.5 May 19, 2015 at 9:19
  • For those interested in compactness, boxcutter is only 22K for the full-screen .exe and 502K for the regular .exe. It is open-source. Works great for me.
    – Frak
    Jan 31, 2019 at 14:57
7

You can use the PowerShell code found here:

[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
function screenshot([Drawing.Rectangle]$bounds, $path) {
   $bmp = New-Object Drawing.Bitmap $bounds.width, >$bounds.height
   $graphics = [Drawing.Graphics]::FromImage($bmp)

   $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)

   $bmp.Save($path)

   $graphics.Dispose()
   $bmp.Dispose()
}

$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, 1000, 900)
screenshot $bounds "C:\screenshot.png"
5

You can use the Pillow python library to take screenshots of the primary monitor

Step1: install Pillow:

pip install -user pillow

Step2: Take screenshots with the following code:

from PIL import ImageGrab
img = ImageGrab.grab()
img.save('screenshot.bmp')
1
  • 1
    First I tried the imagemagic solution, but when I've seen that piece of Python code, I tried it in an interactive Python CLI and a second later I was happy! Thx!!
    – domih
    Jul 30, 2018 at 12:02
1

You can use commercial product snapit to take awesome screenshots from the command line.

2
  • 2
    This is now a commercial product, needs .NET and is not released for Windows 7++. The link given in the answer returns HTTP 404. May 19, 2015 at 9:21
  • Yea the GitHub repo doesn't exist.
    – alpha_989
    Feb 1, 2018 at 19:25
1

On Windows, I managed using the tip from @zacharyliu. For laymen and for those who like portable things I easily did it using Cmder.

  1. Download Cmder. I use the portable version with full installation

  2. Extract Cmder

  3. Open the folder and enter the bin folder (in the same folder as the executable, if not, create one)

  4. Download the NirCmd files (link at the bottom of the page)

  5. Place the NirCmd files in the bin folder

  6. Open Cmder (if it is open restart it)

  7. Use the following code (Saves screenshots.png every 3 seconds 5 times in the C:\screenshots\MONTH-DAY-YEAR\ folder with HOURS-MINUTES-SECONDS.png name):

    cd C:\ && ([ -d screenshots ] || mkdir screenshots) && "nircmdc.exe" loop 5 3000 execmd "cd C:\screenshots\ && ([ -d ~$currdate.MM-dd-yyyy$ ] || mkdir ~$currdate.MM-dd-yyyy$) && nircmdc.exe savescreenshot C:\screenshots\~$currdate.MM-dd-yyyy$\screenshot-~$currtime.HH-mm-ss$.png"
    
  8. Enjoy!

How it works, which date formats are supported, which image formats are supported, and other details:

1

I really dislike answers that rely on third-party software, i spent a bit of time coming up with the solution for my problem, so i'll post it here just in case anyone else needs it.

I combined this answer, with a bit of my own implementation to grab only the powershell window:

add-type -namespace native -name winapi @"
[DllImport("user32.dll")]
public static extern int GetWindowRect(IntPtr hwnd, out System.Management.Automation.Host.Rectangle rect);

[DllImport("user32.dll")]
public static extern bool SetProcessDPIAware();
"@

# necessary, otherwise the dimensions are wrong with different DPIs
[native.winapi]::SetProcessDPIAware()

$rect = [System.Management.Automation.Host.Rectangle]::new(0,0,0,0)
$pshwnd = ([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle
[native.winapi]::GetWindowRect($pshwnd, [ref] $rect)

[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
function screenshot([Drawing.Rectangle]$bounds, $path) {
   $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
   $graphics = [Drawing.Graphics]::FromImage($bmp)

   $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)

   $bmp.Save($path)

   $graphics.Dispose()
   $bmp.Dispose()
}
$bounds = [Drawing.Rectangle]::FromLTRB($rect.Left, $rect.Top, $rect.Right, $rect.Bottom)
screenshot $bounds "screenshot.png"
2
  • This answer isn't what was asked for (in comment, OP clarifies that they do NOT wish to capture the commandline, but instead emails and such)... but +1 anyway, since this can be modified to capture any arbitrary window. Sep 20, 2022 at 16:27
  • I'd also like to take a screenshot of Windows terminal content, including content that's scrolled up off the page if possible, so I'm interested in this answer. But This doesn't have enough information. Is this a script that is supposed to be run or several lines of input that have to be typed in manually. How do I use this code and invoke it?
    – NeilG
    22 hours ago
0

Here's a modification of @npocmaka script that take a full screenshot across all monitors. The usage stays the same.

// 2>nul||@goto :batch
/*
:batch
@echo off
setlocal

:: find csc.exe
set "csc="
for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*csc.exe") do  set "csc=%%#"

if not exist "%csc%" (
   echo no .net framework installed
   exit /b 10
)

if not exist "%~n0.exe" (
   call %csc% /nologo /r:"Microsoft.VisualBasic.dll" /out:"%~n0.exe" "%~dpsfnx0" || (
      exit /b %errorlevel% 
   )
)
%~n0.exe %*
endlocal & exit /b %errorlevel%

*/

// reference  
// https://gallery.technet.microsoft.com/scriptcenter/eeff544a-f690-4f6b-a586-11eea6fc5eb8

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using Microsoft.VisualBasic;

using System.Windows;
using System.Windows.Forms;   // also requires a reference to this assembly
using System.Threading;

/// Provides functions to capture the entire screen, or a particular window, and save it to a file. 

public class ScreenCapture
{

    /// Creates an Image object containing a screen shot the active window 

    public Image CaptureActiveWindow()
    {
        return CaptureWindow(User32.GetForegroundWindow());
    }

    /// Creates an Image object containing a screen shot of the entire desktop 

    public Image CaptureScreen()
    {
        return CaptureWindow(User32.GetDesktopWindow());
    }

    /// Creates an Image object containing a screen shot of a specific window 

    private Image CaptureWindow(IntPtr handle)
    {
        // get te hDC of the target window 
        IntPtr hdcSrc = User32.GetWindowDC(handle);
        // get the size 
        User32.RECT windowRect = new User32.RECT();
        User32.GetWindowRect(handle, ref windowRect);
        int width = windowRect.right - windowRect.left;
        int height = windowRect.bottom - windowRect.top;
        // create a device context we can copy to 
        IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
        // create a bitmap we can copy it to, 
        // using GetDeviceCaps to get the width/height 
        IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
        // select the bitmap object 
        IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
        // bitblt over 
        GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
        // restore selection 
        GDI32.SelectObject(hdcDest, hOld);
        // clean up 
        GDI32.DeleteDC(hdcDest);
        User32.ReleaseDC(handle, hdcSrc);
        // get a .NET image object for it 
        Image img = Image.FromHbitmap(hBitmap);
        // free up the Bitmap object 
        GDI32.DeleteObject(hBitmap);
        return img;
    }

    public void CaptureActiveWindowToFile(string filename, ImageFormat format)
    {
        Image img = CaptureActiveWindow();
        img.Save(filename, format);
    }

    public void CaptureScreenToFile(string filename, ImageFormat format)
    {
        //Image img = CaptureScreen();
        //img.Save(filename, format);
        
        // Create a new thread for demonstration purposes.
        Thread thread = new Thread(() =>
        {
            // Determine the size of the "virtual screen", which includes all monitors.
            int screenLeft   = SystemInformation.VirtualScreen.Left;
            int screenTop    = SystemInformation.VirtualScreen.Top;
            int screenWidth  = SystemInformation.VirtualScreen.Width;
            int screenHeight = SystemInformation.VirtualScreen.Height;

            // Create a bitmap of the appropriate size to receive the screenshot.
            using (Bitmap bmp = new Bitmap(screenWidth, screenHeight))
            {
                // Draw the screenshot into our bitmap.
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.CopyFromScreen(screenLeft, screenTop, 0, 0, bmp.Size);
                }

                // Do something with the Bitmap here, like save it to a file:
                bmp.Save(filename, format);
            }
        });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }

    static bool fullscreen = true;
    static String file = "screenshot.bmp";
    static System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Bmp;
    static String windowTitle = "";

    static void parseArguments()
    {
        String[] arguments = Environment.GetCommandLineArgs();
        if (arguments.Length == 1)
        {
            printHelp();
            Environment.Exit(0);
        }
        if (arguments[1].ToLower().Equals("/h") || arguments[1].ToLower().Equals("/help"))
        {
            printHelp();
            Environment.Exit(0);
        }

        file = arguments[1];
        Dictionary<String, System.Drawing.Imaging.ImageFormat> formats =
        new Dictionary<String, System.Drawing.Imaging.ImageFormat>();

        formats.Add("bmp", System.Drawing.Imaging.ImageFormat.Bmp);
        formats.Add("emf", System.Drawing.Imaging.ImageFormat.Emf);
        formats.Add("exif", System.Drawing.Imaging.ImageFormat.Exif);
        formats.Add("jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
        formats.Add("jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
        formats.Add("gif", System.Drawing.Imaging.ImageFormat.Gif);
        formats.Add("png", System.Drawing.Imaging.ImageFormat.Png);
        formats.Add("tiff", System.Drawing.Imaging.ImageFormat.Tiff);
        formats.Add("wmf", System.Drawing.Imaging.ImageFormat.Wmf);


        String ext = "";
        if (file.LastIndexOf('.') > -1)
        {
            ext = file.ToLower().Substring(file.LastIndexOf('.') + 1, file.Length - file.LastIndexOf('.') - 1);
        }
        else
        {
            Console.WriteLine("Invalid file name - no extension");
            Environment.Exit(7);
        }

        try
        {
            format = formats[ext];
        }
        catch (Exception e)
        {
            Console.WriteLine("Probably wrong file format:" + ext);
            Console.WriteLine(e.ToString());
            Environment.Exit(8);
        }


        if (arguments.Length > 2)
        {
            windowTitle = arguments[2];
            fullscreen = false;
        }

    }

    static void printHelp()
    {
        //clears the extension from the script name
        String scriptName = Environment.GetCommandLineArgs()[0];
        scriptName = scriptName.Substring(0, scriptName.Length);
        Console.WriteLine(scriptName + " captures the screen or the active window and saves it to a file.");
        Console.WriteLine("");
        Console.WriteLine("Usage:");
        Console.WriteLine(" " + scriptName + " filename  [WindowTitle]");
        Console.WriteLine("");
        Console.WriteLine("filename - the file where the screen capture will be saved");
        Console.WriteLine("     allowed file extensions are - Bmp,Emf,Exif,Gif,Icon,Jpeg,Png,Tiff,Wmf.");
        Console.WriteLine("WindowTitle - instead of capture whole screen you can point to a window ");
        Console.WriteLine("     with a title which will put on focus and captuted.");
        Console.WriteLine("     For WindowTitle you can pass only the first few characters.");
        Console.WriteLine("     If don't want to change the current active window pass only \"\"");
    }

    public static void Main()
    {
        User32.SetProcessDPIAware();
        
        parseArguments();
        ScreenCapture sc = new ScreenCapture();
        if (!fullscreen && !windowTitle.Equals(""))
        {
            try
            {

                Interaction.AppActivate(windowTitle);
                Console.WriteLine("setting " + windowTitle + " on focus");
            }
            catch (Exception e)
            {
                Console.WriteLine("Probably there's no window like " + windowTitle);
                Console.WriteLine(e.ToString());
                Environment.Exit(9);
            }


        }
        try
        {
            if (fullscreen)
            {
                Console.WriteLine("Taking a capture of the whole screen to " + file);
                sc.CaptureScreenToFile(file, format);
            }
            else
            {
                Console.WriteLine("Taking a capture of the active window to " + file);
                sc.CaptureActiveWindowToFile(file, format);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Check if file path is valid " + file);
            Console.WriteLine(e.ToString());
        }
    }

    /// Helper class containing Gdi32 API functions 

    private class GDI32
    {

        public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter 
        [DllImport("gdi32.dll")]
        public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest,
          int nWidth, int nHeight, IntPtr hObjectSource,
          int nXSrc, int nYSrc, int dwRop);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth,
          int nHeight);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    }


    /// Helper class containing User32 API functions 

    private class User32
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();
        [DllImport("user32.dll")]
        public static extern int SetProcessDPIAware();
    }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .