Selectors and Clipping

Capture specific elements using CSS selectors, expand padding, or define manual clip regions. Rather than screenshotting an entire page and cropping afterward, nokap can target individual DOM elements directly, producing tightly framed images with no post-processing required. This page explains how to use single selectors, combine multiple selectors, add padding around elements, and specify exact pixel-level clip rectangles.

CSS Selectors

The most common way to target a specific part of a page is with a CSS selector. When you pass a selector, nokap locates the matching element in the DOM, computes its bounding box, and captures only that region. This works for both image and PDF output.

import nokap

# Capture just the main heading
nokap.webshot("https://example.com", "heading.png", selector="h1")

# Capture by class
nokap.webshot("https://example.com", "nav.png", selector=".navigation")

# Capture by ID
nokap.webshot("https://example.com", "hero.png", selector="#hero-section")

Multiple Selectors

Sometimes the content you need spans multiple elements that aren’t wrapped in a single container. In those cases, pass a list of selectors and nokap computes the union bounding box (the smallest rectangle that encompasses all matched elements):

# Capture header and footer together
nokap.webshot(
    "page.html",
    "combined.png",
    selector=["header", "footer"]
)

Elements with zero width or height (invisible elements) are automatically excluded from the union calculation. This makes it safe to include selectors that might not be visible on every page.

Expand / Padding

Capturing an element right at its bounding box edge can feel cramped. The expand parameter adds breathing room (in pixels) around the element, giving you a more polished result without needing to modify the page’s CSS:

# Add 10px padding on all sides
nokap.webshot("page.html", "padded.png", selector="table", expand=10)

For asymmetric padding, pass a 4-tuple of (top, right, bottom, left):

# 20px top/bottom, 10px left/right
nokap.webshot(
    "page.html",
    "padded.png",
    selector="table",
    expand=(20, 10, 20, 10),
)

A small expand value (5–10px) is usually enough to prevent visual crowding. Larger values are useful when the surrounding whitespace is part of the design intent.

Clip Rectangle

When you need pixel-perfect control over the captured region (or when the area of interest doesn’t correspond to any single DOM element) use cliprect. It takes a tuple of (x, y, width, height) in CSS pixels, specifying an exact rectangle on the page:

# Capture a 400×300 region starting at (50, 100)
nokap.webshot(
    "https://example.com",
    "region.png",
    cliprect=(50, 100, 400, 300),
)
Warning

selector and cliprect are mutually exclusive. Passing both raises an error.

Selectors with from_html()

When rendering HTML strings with from_html(), the default selector is "html", which captures the entire rendered page. For most use cases (especially when working with generated HTML from tools like Great Tables) you’ll want to override this with a more specific selector to capture just the element of interest:

html = """
<div style="padding: 2rem;">
  <table id="data-table">
    <tr><th>Name</th><th>Value</th></tr>
    <tr><td>Alpha</td><td>100</td></tr>
    <tr><td>Beta</td><td>200</td></tr>
  </table>
  <p>Footer text (not captured)</p>
</div>
"""

nokap.from_html(html, "table.png", selector="#data-table", expand=5)

Automatic Width Detection

A common frustration when capturing wide content (like a table with many columns) is that the default viewport width clips the element. nokap solves this automatically: when it detects that an element’s width fills or exceeds the viewport, it temporarily widens the viewport to allow the element to render at its natural/intrinsic width. The result is a capture that shows the full content regardless of how wide it is.

This behavior uses a two-pass heuristic to distinguish between two types of elements:

  • Intrinsic-width elements (tables, code blocks): These have a fixed natural width determined by their content. If the viewport constrains them, nokap widens the viewport and captures the full content.
  • Fluid-layout elements (<main>, <div> with percentage widths): These grow with the viewport and have no fixed intrinsic width. nokap detects this pattern and reverts to the original viewport to avoid producing output with unnecessary whitespace on both sides.

No manual vwidth configuration is needed in either case. The detection works for both image and PDF output, so wide tables are always captured completely whether you’re producing a PNG or an element-bounded PDF.

Selector Errors

When a selector doesn’t match any element in the rendered page, nokap raises a SelectorError immediately rather than producing a blank or broken capture. This makes it easy to catch typos or selectors that depend on content that hasn’t loaded yet:

import nokap
from nokap import SelectorError

try:
    nokap.webshot("page.html", "out.png", selector="#nonexistent")
except SelectorError as e:
    print(f"Selector failed: {e}")
    # "No element matches selector: '#nonexistent'"

Next Steps

With selectors, expand, clip rectangles, and automatic width detection, you can precisely control what gets captured, from a single heading to a wide data table with dozens of columns. These tools eliminate the need for post-processing crops and ensure your output matches exactly what you see in the browser.

Selectors become especially powerful when combined with PDF output, where a targeted selector produces a compact, element-sized PDF rather than a full page. Head to the PDF guide to see how these concepts come together.