Here's a way to take a fullscreen screenshot using the PIL ImageGrab module, that is already installed in many Python environments:
fullscreenShot[] := ExternalEvaluate["Python", "import PIL.ImageGrab PIL.ImageGrab.grab()"]
Here is a function to take a screenshot of a specified screen rectangle using the same module:
screenShot = ExternalFunction["Python", "import PIL.ImageGrab def screenshot(left_x, top_y, right_x, bottom_y): return PIL.ImageGrab.grab(bbox=(left_x, top_y, right_x, bottom_y))" ]

Here is a pure Python function to take a screenshot of the current active window on Windows(1),(2):
activeWindowScreenShot[] := ExternalEvaluate["Python", "import ctypes from ctypes import wintypes import PIL.ImageGrab user32 = ctypes.windll.user32 handle = user32.GetForegroundWindow() rect = wintypes.RECT() user32.GetWindowRect(handle, ctypes.pointer(rect)) PIL.ImageGrab.grab(bbox=(rect.left,rect.top,rect.right,rect.bottom))"]
And here is a function to take a screenshot of the current Notebook window:
Clear[currentNotebookImage0] currentNotebookImage0[margins_ : 6] := Module[{screenInformation = First[SystemInformation["Devices", "ScreenInformation"]], windowMargins = AbsoluteCurrentValue[WindowMargins], resolution, screenArea, width, height, left, right, bottom, top}, {resolution, screenArea} = {"Resolution", "ScreenArea"} /. screenInformation; {width, height} = Round[screenArea[[All, 2]]*resolution/72.]; {{left, right}, {bottom, top}} = Round[If[MatrixQ[windowMargins], windowMargins + {{margins, margins}, {margins, margins}}, {{0, 0}, {0, 0}}]* resolution/72.]; {{left, right}, {top, bottom}} = {Clip[{left, width - right}, {0, width}], Clip[{top, height - bottom}, {0, height}]}; ExternalEvaluate["Python", <|"Command" -> "import PIL.ImageGrab def screenshot(left_x, top_y, right_x, bottom_y): return PIL.ImageGrab.grab(bbox=(left_x, top_y, right_x, bottom_y))", "Arguments" -> {left, top, right, bottom}|>]]
The default value 6 for the parameter margins is taken from what returns AbsoluteCurrentValue[WindowMargins] when the Notebook window is maximized on my system (Mathematica 13.1.0 on Windows 10 x64):
AbsoluteCurrentValue[WindowMargins]
-6
With Mathematica 12.3.1 on the same machine I get the value -8.
The value -6 means that when the Notebook window is maximized, Mathematica thinks that the window is actually cropped by 6 printer's points from all sides. Translating into normal language, this means that the window is always enlarged by 6 printer's points on all sides as compared to its maximized size. The latter is equivalent in the meaning to the ImageMargins option of Graphics in Mathematica. Hence the margins parameter name.
These considerations are confirmed by comparing the values of the window width obtained from AbsoluteCurrentValue[WindowSize] and AbsoluteCurrentValue[WindowMargins] (output is for Mathematica 13.1.0):
windowMargins = AbsoluteCurrentValue[WindowMargins]; screenArea = "ScreenArea" /. First[SystemInformation["Devices", "ScreenInformation"]]; windowSize = AbsoluteCurrentValue[WindowSize]; screenArea[[All, 2]] - Total /@ windowMargins - windowSize
{12., 44.25}
(for Mathematica 12.3.1 the output is {16, 59}).
We see that the window width reported by AbsoluteCurrentValue[WindowSize] is 6*2 = 12 printer's points smaller than the value obtain from AbsoluteCurrentValue[WindowMargins]. Hence we can calculate the value for the parameter margins from AbsoluteCurrentValue[WindowSize] as follows:
margins = If[MatrixQ[windowMargins], (screenArea[[1, 2]] - Total[windowMargins[[1]]] - windowSize[[1]])/2, -windowMargins]
6.
With this definition, currentNotebookImage0 can be rewritten as follows:
Clear[currentNotebookImage] currentNotebookImage[] := Module[{screenInformation = First[SystemInformation["Devices", "ScreenInformation"]], windowMargins = AbsoluteCurrentValue[WindowMargins], margins, left, right, bottom, top, windowSize = AbsoluteCurrentValue[WindowSize], resolution, screenArea, width, height}, {resolution, screenArea} = {"Resolution", "ScreenArea"} /. screenInformation; margins = If[MatrixQ[windowMargins], (screenArea[[1, 2]] - Total[windowMargins[[1]]] - windowSize[[1]])/2, -windowMargins]; {width, height} = Round[screenArea[[All, 2]]*resolution/72.]; {{left, right}, {bottom, top}} = Round[(windowMargins + margins*{{1, 1}, {1, 1}})*resolution/72.]; {{left, right}, {top, bottom}} = {Clip[{left, width - right}, {0, width}], Clip[{top, height - bottom}, {0, height}]}; ExternalEvaluate["Python", <|"Command" -> "import PIL.ImageGrab def screenshot(left_x, top_y, right_x, bottom_y): return PIL.ImageGrab.grab(bbox=(left_x, top_y, right_x, bottom_y))", "Arguments" -> {left, top, right, bottom}|>]]
The main advantage of this approach is that it does not require "magic" numbers and works perfectly well both with version 13.1.0 and 12.3.1:
currentNotebookImage[]

It is easy to rewrite the great cCurrentNotebookImage[] function by Ben Izd using the new method for determining the window rectangle coordinates:
Needs["JLink`"]; LoadJavaClass /@ {"java.awt.Robot", "java.awt.Rectangle", "java.io.ByteArrayOutputStream", "javax.imageio.ImageIO"}; Clear[cCurrentNotebookImage] cCurrentNotebookImage[] := Module[{screenInformation = First[SystemInformation["Devices", "ScreenInformation"]], windowMargins = AbsoluteCurrentValue[WindowMargins], margins, left, right, bottom, top, windowSize = AbsoluteCurrentValue[WindowSize], resolution, screenArea, width, height}, {resolution, screenArea} = {"Resolution", "ScreenArea"} /. screenInformation; margins = If[MatrixQ[windowMargins], (screenArea[[1, 2]] - Total[windowMargins[[1]]] - windowSize[[1]])/2, -windowMargins]; {width, height} = Round[screenArea[[All, 2]]*resolution/72.]; {{left, right}, {bottom, top}} = Round[(windowMargins + margins*{{1, 1}, {1, 1}})*resolution/72.]; {{left, right}, {top, bottom}} = {Clip[{left, width - right}, {0, width}], Clip[{top, height - bottom}, {0, height}]}; JavaBlock[robot = JavaNew["java.awt.Robot"]; temp = JavaNew["java.io.ByteArrayOutputStream"]; img = robot@ createScreenCapture[ JavaNew["java.awt.Rectangle", left, top, right - left, bottom - top]]; ImageIO`write[img, "png", temp]; ImportByteArray[ByteArray@Mod[temp@toByteArray[], 2^8], "PNG"]]]
There is an old but still working GUIScreenShot[] from "GUIKit`". To take a fullscreen screenshot, just evaluate:
Needs["GUIKit`"] GUIScreenShot[]
To take a screenshot of the currently active Notebook, use the following function:
gCurrentNotebookImage[] := Module[{screenInformation = First[SystemInformation["Devices", "ScreenInformation"]], windowMargins = AbsoluteCurrentValue[WindowMargins], margins, left, right, bottom, top, windowSize = AbsoluteCurrentValue[WindowSize], resolution, screenArea, width, height}, {resolution, screenArea} = {"Resolution", "ScreenArea"} /. screenInformation; margins = If[MatrixQ[windowMargins], (screenArea[[1, 2]] - Total[windowMargins[[1]]] - windowSize[[1]])/2, -windowMargins]; {width, height} = Round[screenArea[[All, 2]]*resolution/72.]; {{left, right}, {bottom, top}} = Round[(windowMargins + margins*{{1, 1}, {1, 1}})*resolution/72.]; {{left, right}, {top, bottom}} = {Clip[{left, width - right}, {0, width}], Clip[{top, height - bottom}, {0, height}]}; GUIKit`GUIScreenShot[{{left, right}, {top, bottom}}]]
ModulewithJavaBlockand insertrobot = JavaNew["java.awt.Robot"];, to prevent memory leaking. $\endgroup$