Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →If Selenium captures the wrong part of a page, start with the element-level API: locate the intended element after the page has settled, bring it into view, then call element.screenshot("card.png"). Most shifted or incomplete captures come from layout changes, scrolling, stale element references, or mixing CSS-pixel coordinates with screenshot pixels—not from the screenshot call itself.
Capture the element directly first
Selenium’s Python WebElement.screenshot() saves the current element as a PNG. The API also provides screenshot_as_png and screenshot_as_base64 when you need the image in memory rather than a file. Use a filename ending in .png for file output. See the Selenium WebElement API.
from selenium.webdriver.common.by import By
card = driver.find_element(By.CSS_SELECTOR, "article.card")
card.screenshot("card.png")
# Or keep the PNG bytes in memory:
png_bytes = card.screenshot_as_png
This is the simplest supported route when the goal is one element. Selenium scrolls the element into view and measures its rectangle as part of its element-screenshot behavior; the resulting capture is therefore sensitive to the page’s scroll state and geometry. The implementation is documented in Selenium’s WebElement implementation.
Use a stable capture sequence
A locator becoming available does not mean the layout has stopped changing. Fonts, images, ads, responsive content, and client-side rendering can move or resize a target after it first appears. Wait for visibility, scroll deliberately, locate the element again, and allow a rendering frame before taking the screenshot.
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
- Wait for the target: use an explicit wait rather than capturing immediately after navigation.
- Scroll intentionally: center the target in the viewport, unless your test depends on a particular sticky-header or scroll state.
- Re-find it: a framework rerender can replace the node after your first lookup.
- Wait for rendering: allow at least one animation frame after scrolling and any state changes that affect layout.
- Capture the element: use
WebElement.screenshot()for a direct element image.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
locator = (By.CSS_SELECTOR, "article.card")
wait = WebDriverWait(driver, 15)
element = wait.until(EC.visibility_of_element_located(locator))
driver.execute_script(
"arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});",
element,
)
# Re-query after scrolling in case a rerender replaced the original node.
element = wait.until(EC.visibility_of_element_located(locator))
driver.execute_async_script(
"const done = arguments[arguments.length - 1]; requestAnimationFrame(() => done());"
)
element.screenshot("card.png")
The wait above checks visibility, not that dimensions remain unchanged for a particular duration. If the site continues to animate or load content, wait for that site-specific condition too—for example, an image’s complete state, disappearance of a loading indicator, or stable dimensions across consecutive checks.
Inspect geometry before changing coordinates
Log both Selenium’s element rectangle and the browser’s viewport-relative rectangle immediately before capture. Also record the window and viewport sizes, scroll offsets, and device pixel ratio. Selenium describes rect as a dictionary of element size and location in its WebElement API.
Rank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
from selenium.webdriver.common.by import By
locator = (By.CSS_SELECTOR, "article.card")
element = driver.find_element(*locator)
geometry = driver.execute_script("""
const r = arguments[0].getBoundingClientRect();
return {
x: r.x, y: r.y, width: r.width, height: r.height,
scrollX: window.scrollX, scrollY: window.scrollY,
viewportWidth: document.documentElement.clientWidth,
viewportHeight: window.innerHeight,
devicePixelRatio: window.devicePixelRatio
};
""", element)
print("WebElement rect:", element.rect)
print("Window size:", driver.get_window_size())
print("Viewport geometry:", geometry)
element.screenshot("card.png")
getBoundingClientRect() reports coordinates relative to the viewport. Do not add scrollY to those coordinates when cropping a viewport screenshot; that would shift the crop a second time. Scroll offsets belong in a conversion to document coordinates for a different capture method.
Understand scroll containers and partial captures
An element screenshot is not a promise to stitch every hidden part of a scrollable region into one image. Selenium’s documented element-screenshot behavior captures only the currently scrolled content of a scrollable container; content outside that visible portion may be absent. See Selenium’s element screenshot documentation.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
When the page itself scrolls
Use scrollIntoView() on the target, then capture the fresh element reference. A sticky header may cover the target after the scroll, and the header can make the visible pixels appear to belong to a different section. Centering the element often helps, but inspect the final screenshot and the element’s rectangle rather than assuming the scroll landed as expected.
When a nested panel scrolls
If the target is inside a panel with its own scrollbar, the panel—not the document—may own the relevant content position. Scroll that container deliberately, then capture the element or capture successive positions. Changing window.scrollY alone will not reveal content hidden inside an independently scrolling panel.
When the target is taller than its visible box
Capture deliberate scroll segments and combine them if you need the full content. A single element screenshot should not be treated as a full-page stitching operation. Keep track of each segment’s scroll position and overlap so the assembled image does not omit or duplicate content.
Rank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
Keep CSS pixels and screenshot pixels separate
Browser geometry such as getBoundingClientRect() is expressed in CSS pixels. A screenshot can contain more image pixels than the CSS viewport because of device scale; Selenium’s screenshot documentation notes that device scale can make an image twice as large or more. See Selenium window and screenshot documentation. The actual image-to-viewport scale is safer to calculate from the PNG dimensions than to assume it equals window.devicePixelRatio.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsManual crop when you need padding or a composite
Manual cropping is useful when the desired area includes padding around an element, spans multiple elements, or you are working around driver-specific element clipping. Capture the viewport, read the viewport-relative rectangle, and scale the CSS coordinates to the actual screenshot dimensions:
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
from io import BytesIO
from PIL import Image
from selenium.webdriver.common.by import By
element = driver.find_element(By.CSS_SELECTOR, "article.card")
page_png = driver.get_screenshot_as_png()
rect = driver.execute_script("""
const r = arguments[0].getBoundingClientRect();
return {x: r.x, y: r.y, width: r.width, height: r.height};
""", element)
image = Image.open(BytesIO(page_png))
viewport = driver.execute_script("""
return {
width: document.documentElement.clientWidth,
height: window.innerHeight
};
""")
scale_x = image.width / viewport["width"]
scale_y = image.height / viewport["height"]
box = (
round(rect["x"] * scale_x),
round(rect["y"] * scale_y),
round((rect["x"] + rect["width"]) * scale_x),
round((rect["y"] + rect["height"]) * scale_y),
)
image.crop(box).save("card-crop.png")
In that example, remove the leading space before element = if pasting into a top-level script; Python does not allow an unexpected indent. The crop uses the screenshot’s measured width and height against the browser’s CSS viewport dimensions. This handles differing horizontal and vertical scales instead of assuming one fixed Retina multiplier. Ensure the intended element is in the captured viewport and that the rectangle is not covered by overlays.
Check the common causes of a wrong section
- Wrong or duplicate match: confirm the selector resolves to the intended element rather than a hidden duplicate, and inspect the matched element’s identifying text or attributes.
- Layout changed after lookup: wait for relevant content and fonts, then re-find the element just before capture.
- Stale WebElement: if a framework rerender replaced the node, discard the old reference and locate again.
- Incorrect frame: switch to the iframe containing the target before locating it; a locator in the top-level document cannot directly select an iframe’s contents.
- Shadow DOM: query through the appropriate shadow root rather than treating a shadow descendant as an ordinary page descendant.
- Nested scrolling: move the scroll container that owns the hidden content, not just the document.
- Overlays or transformations: fixed headers, dialogs, cookie banners, CSS transforms, browser zoom, and animations can cover or move visible pixels relative to the expected section.
- Headless viewport mismatch: set the browser window size intentionally and compare the screenshot dimensions with the JavaScript viewport before applying a crop.
Troubleshoot by symptom
| Symptom | Likely cause | What to do |
|---|---|---|
| The image shows a nearby section or the element appears shifted. | The layout moved after the first lookup, the page scrolled, or a sticky overlay changed what is visible. | Wait for the final layout, scroll deliberately, re-find the element, log its rectangle, and capture again. |
| The screenshot is cut off at the bottom of a panel. | The target is inside a scrollable box and only the currently visible portion was captured. | Scroll the owning container and capture segments, or use a deliberate full-page strategy where appropriate. |
| A manual crop is offset on a Retina or high-DPI display. | CSS coordinates were used directly as image-pixel coordinates. | Calculate separate scale_x and scale_y from the PNG dimensions and CSS viewport dimensions. |
| The intended element can no longer be captured. | A rerender replaced the node, or the driver is in the wrong iframe context. | Re-query immediately before capture; switch to the correct frame before finding the element. |
| The correct rectangle still contains the wrong visible pixels. | A fixed overlay, transform, zoom, animation, or partial viewport clipping affects rendering. | Inspect computed geometry and screenshot state, disable or wait out animations where possible, and account for overlays. |
Or skip the browser setup
If you need a screenshot without managing a Selenium browser session, ScreenshotNeo is a website screenshot API and MCP server for developers. Its one-request API can return an image or PDF. The example below follows the ScreenshotNeo API documentation; replace the target URL and use your API key.
Quick Recap
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo accepts cookie or consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, with page-verdict and billed-status response headers. Its MCP server 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 without a card; paid plans start at $5 for 3,000 shots. Sign up for the free plan.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

