Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Short answer: scroll a PuppeteerSharp page only when scrolling is needed to trigger the site’s lazy loading, then wait for a concrete ready condition and call PdfAsync. Scrolling does not have a documented, general effect of cropping the PDF to the visible viewport. PuppeteerSharp generates PDFs with print CSS media by default; call EmulateMediaTypeAsync(MediaType.Screen) first when the page’s screen styles are required.

What scrolling does—and does not do

A Chromium PDF is a print rendering of the document, not a screenshot of whatever pixels are currently visible. The PuppeteerSharp Page API describes PdfAsync as generating a PDF with print CSS media. The documentation does not promise that window.scrollTo, a wheel event, or the current scroll offset becomes PDF crop bounds. The result can vary with the page layout, Chromium build, and PuppeteerSharp version.

Therefore decide which output you need before writing code:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Whole printable document: load the required content, optionally scroll to activate lazy loading, then call PdfAsync.
  • Screen-styled document: emulate screen media before calling PdfAsync.
  • One visible scrolled viewport: treat this as a separate capture problem. The consulted API references do not document a PDF viewport-clipping option, so validate your exact runtime and inspect the generated file rather than assuming the scroll offset is honored.

For a guaranteed single viewport image, use a screenshot workflow instead of presenting an ordinary PDF as a crop.

#1 Best Overall
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Minimal PuppeteerSharp PDF workflow

The official examples show the essential sequence: launch a headless browser, create a page, navigate, wait for a known selector, and generate the file (official examples).

using PuppeteerSharp;

var url = "https://example.com/article";

await new BrowserFetcher().DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
    Headless = true
});

await using var page = await browser.NewPageAsync();
await page.GoToAsync(url, new NavigationOptions
{
    WaitUntil = new[] { WaitUntilNavigation.Networkidle0 }
});

await page.WaitForSelectorAsync("main");
await page.PdfAsync("article.pdf");

Networkidle0 is useful for pages that settle network requests, but it is not proof that every application has rendered its lower sections. A selector representing the actual finished content is a stronger readiness check.

Use screen CSS when the print stylesheet is wrong

Print media is the default. If the page’s print stylesheet hides navigation, changes colors, or rearranges columns in a way you do not want, select screen media immediately before PDF generation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.EmulateMediaTypeAsync(MediaType.Screen);
await page.PdfAsync("screen-styled.pdf", new PdfOptions
{
    PrintBackground = true,
    WaitForFonts = true
});

The PdfOptions reference documents WaitForFonts as waiting for document.fonts.ready and defaulting to true. It also documents PrintBackground as defaulting to false and Scale as defaulting to 1, with a range of 0.1 to 2.

Rank #2
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Loading content revealed by scrolling

Infinite feeds, image lazy loading, and intersection-observer components may not fetch lower content until it enters or approaches the viewport. In that case scrolling is a loading trigger, not a PDF crop instruction.

Scroll incrementally and wait for growth

async Task ScrollToLoadEverythingAsync(IPage page)
{
    var previousHeight = 0L;

    for (var pass = 0; pass < 30; pass++)
    {
        var height = await page.EvaluateExpressionAsync<long>(
            "document.documentElement.scrollHeight");

        await page.EvaluateExpressionAsync(
            "window.scrollTo(0, document.documentElement.scrollHeight)");
        await Task.Delay(300);

        var newHeight = await page.EvaluateExpressionAsync<long>(
            "document.documentElement.scrollHeight");

        if (newHeight == height && newHeight == previousHeight)
            break;

        previousHeight = height;
    }
}

This loop is a generic trigger, not a guarantee. A site may paginate through a button, require a particular scroll container, or stop loading after a server-side limit. Prefer the site’s own completion signal when one exists.

Wait for a concrete completion condition

Wait for a final card, an application-specific “loaded” marker, or a known count of items. For example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.WaitForSelectorAsync("article[data-loaded='true']");
// Or wait for a site-specific marker:
await page.WaitForSelectorAsync("#feed-finished");

A fixed delay can be useful as a small settling pause, but it cannot establish that a slow request, failed image, or deferred JavaScript operation completed. Generate the PDF only after the condition that matters to your document is true.

A complete scrolled-page example

using PuppeteerSharp;

var url = "https://example.com/long-page";
await new BrowserFetcher().DownloadAsync();

await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
    Headless = true
});
await using var page = await browser.NewPageAsync();

await page.SetViewportAsync(new ViewPortOptions
{
    Width = 1440,
    Height = 900,
    DeviceScaleFactor = 1
});

await page.GoToAsync(url, new NavigationOptions
{
    WaitUntil = new[] { WaitUntilNavigation.Networkidle0 },
    Timeout = 60_000
});

await page.WaitForSelectorAsync("main");
await ScrollToLoadEverythingAsync(page);
await page.WaitForSelectorAsync("#feed-finished");

await page.EmulateMediaTypeAsync(MediaType.Screen);
await page.PdfAsync("long-page.pdf", new PdfOptions
{
    Format = PaperFormat.A4,
    PrintBackground = true,
    WaitForFonts = true,
    Scale = 1
});

static async Task ScrollToLoadEverythingAsync(IPage page)
{
    var previousHeight = 0L;
    for (var pass = 0; pass < 30; pass++)
    {
        var height = await page.EvaluateExpressionAsync<long>(
            "document.documentElement.scrollHeight");
        await page.EvaluateExpressionAsync(
            "window.scrollTo(0, document.documentElement.scrollHeight)");
        await Task.Delay(300);
        var newHeight = await page.EvaluateExpressionAsync<long>(
            "document.documentElement.scrollHeight");
        if (newHeight == height && newHeight == previousHeight) break;
        previousHeight = height;
    }
}

For a page whose lazy loader listens to an inner element, replace window.scrollTo with JavaScript that updates that element’s scrollTop. For a “Load more” control, click it and wait for the item count to increase instead of repeatedly scrolling the document.

PDF options that affect appearance

Keep rendering style, content readiness, and page geometry as separate decisions. The API reference includes options for paper size, custom width and height, scale, margins, backgrounds, tagged output, headers and footers, page ranges, and font readiness.

  • Paper and margins: choose a format such as A4 or set explicit dimensions; margins prevent headers, footers, and body content from colliding.
  • Scale: stay within the documented 0.1–2 range. Lower values fit more content but reduce legibility.
  • PrintBackground: enable it when colored panels or background images are part of the intended design.
  • WaitForFonts: leave the documented default of true unless you have a measured reason to change it.
  • Headers and footers: remember that templates use print-time markup and may need their own CSS.
  • Page ranges: use them after verifying pagination; they do not turn a scroll position into a crop rectangle.

When you need one visible viewport

If the requirement is “the region shown after scrolling to 2,000 pixels,” do not infer that PdfAsync supports it. The available Page and PdfOptions references describe document PDF generation, not a scroll-offset clipping parameter (Page API, Page source). Test the installed PuppeteerSharp and Chrome versions, and inspect page boundaries, fixed elements, and scaling in the output. A screenshot of a controlled viewport is usually the more direct artifact; convert that image to a PDF only if your workflow specifically requires a PDF container.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshooting

The PDF contains only the initial items

The loader probably needs a scroll event, an inner scroll container, a button click, or a completion wait. Inspect which element actually scrolls, trigger that element, and wait for a selector or item-count change. Do not rely on a longer arbitrary delay.

The PDF looks different from the browser

Print CSS is active by default. Call EmulateMediaTypeAsync(MediaType.Screen) before PdfAsync, and enable PrintBackground if backgrounds are intentionally part of the output.

Fonts or icons are missing

Keep WaitForFonts = true, wait for a stable content marker, and verify that the headless browser can reach the font origin. A font request blocked by authentication, CSP, or a network policy cannot be repaired by PDF options.

Navigation times out

Set a timeout appropriate for the site, log the URL and exception, and use a narrower readiness strategy when the page keeps long-lived analytics connections open. Waiting for the required selector can be more reliable than requiring global network idleness.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Content is duplicated after scrolling

Virtualized lists may recycle DOM nodes. Capture after the application reports its settled state, and verify the PDF text or page count. If the list is intentionally virtualized, use the application’s export endpoint or pagination rather than assuming all records exist in the DOM.

Best Value
Sale
JavaScript and jQuery: Interactive Front-End Web Development
  • JavaScript Jquery
  • Introduces core programming concepts in JavaScript and jQuery
  • Uses clear descriptions, inspiring examples, and easy-to-follow diagrams

The output is blank or missing protected content

Check authentication, cookies, redirects, bot checks, and resource requests in the same headless context. Confirm the page reached the expected URL and selector before generating the file.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost considerations

  • Reuse a browser process for multiple pages, but create an isolated page or context per job so cookies and navigation state do not leak.
  • Set an upper bound on scroll passes and overall job time; an endless feed otherwise creates an unbounded PDF.
  • Capture at the smallest viewport and scale that meets readability requirements. Large dimensions and background images increase rendering and file time.
  • Save diagnostic metadata such as final URL, page title, scroll passes, and the readiness condition used. Keep the PDF itself as the verification artifact.
  • PuppeteerSharp PDF generation runs in Chrome headless, as stated by the Page API. Pin and test the PuppeteerSharp and Chromium versions used in production.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server when you need a rendered capture without maintaining PuppeteerSharp and Chromium. Its clean-shot pipeline accepts consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

For API parameters and all options, see the ScreenshotNeo documentation. A one-call PDF or image request can look like this (change the target URL as needed):

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo supports full-page captures with lazy images loaded, CSS-selector element captures, device presets or custom viewports, retina scale, PDF paper and margin controls, custom CSS and JavaScript, click and wait conditions, request blocking, headers and cookies, timezone and geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, and a usage API. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Choosing the right approach

Requirement Best starting point Important qualification
Control over .NET page logic and authentication PuppeteerSharp You own Chromium lifecycle, waits, and maintenance.
Print document with dynamic sections PuppeteerSharp plus explicit readiness checks Scrolling triggers loading; it is not documented as a crop control.
Screen-style rendering PuppeteerSharp with screen media emulation Call EmulateMediaTypeAsync(MediaType.Screen) before PDF generation.
Managed capture, clean pages, or AI-agent access ScreenshotNeo Use its API or MCP tools and inspect verdict/billing headers.

Frequently Asked Questions

Does PuppeteerSharp PDF generation capture only the current scroll position?

No general behavior is documented. Treat scrolling as a way to trigger page code, not as a PDF crop instruction, and verify the output for your installed versions.

How can I force screen media for a PDF?

Call await page.EmulateMediaTypeAsync(MediaType.Screen) immediately before PdfAsync.

What is the safest wait condition for an infinite page?

Use a site-specific finished marker, final selector, or item-count condition, together with a maximum number of scroll passes and a job timeout.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can I generate a PDF of just one scrolled viewport?

The cited PuppeteerSharp PDF references do not document viewport clipping by scroll offset. Validate a custom approach in your runtime, or capture a viewport screenshot and package it as a PDF if that meets your requirement.

Quick Recap

SaleBestseller No. 1
HTML and CSS: Design and Build Websites
HTML and CSS: Design and Build Websites
HTML CSS Design and Build Web Sites; Comes with secure packaging; It can be a gift option
$14.94
SaleBestseller No. 2
Web Design with HTML, CSS, JavaScript and jQuery Set
Web Design with HTML, CSS, JavaScript and jQuery Set
Brand: Wiley; Set of 2 Volumes
$35.05
SaleBestseller No. 3
SaleBestseller No. 5
JavaScript and jQuery: Interactive Front-End Web Development
JavaScript and jQuery: Interactive Front-End Web Development
JavaScript Jquery; Introduces core programming concepts in JavaScript and jQuery; Uses clear descriptions, inspiring examples, and easy-to-follow diagrams
$22.28

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.