Skip to content

Content Fetching Overview

Content fetching retrieves the rendered content of a web page through a headless browser, behind the IWebContentFetcher abstraction.

Fetching a Page

var fetcher = provider.GetRequiredService<IWebContentFetcher>();

var content = await fetcher.FetchAsync("https://test.example.com");
if (!content.Success)
{
    logger.LogWarning("Fetch failed: {Error}", content.ErrorMessage);
    return;
}

Console.WriteLine(content.FinalUrl);   // URL after any redirects
Console.WriteLine(content.Content);    // page content as plain text

The returned WebContent record:

Property Description
Success Whether the fetch completed successfully
Content Page content extracted from the rendered body (HTML stripped)
ErrorMessage Failure reason when Success is false
FinalUrl The URL of the page after redirects

Limiting Content Length

By default FetchAsync returns the full page content without truncation. Pass maxContentLength to limit the output to a specific number of characters:

// Get at most 8000 characters of content
var content = await fetcher.FetchAsync("https://test.example.com", maxContentLength: 8000);

The returned content is cut to exactly the specified character count — no truncation indicator is appended. If you need to signal to downstream consumers that content was trimmed, append your own suffix after the call.

Passing null (the default) returns everything. Passing a value ≤ 0 throws ArgumentOutOfRangeException.

Engine Implementations

Engine Implementation
EBrowserEngine.Playwright PlaywrightContentFetcher
EBrowserEngine.CloakBrowser CloakBrowserContentFetcher

Both accept a headless flag in their constructor (true by default) and are registered for you by AddBrowserServices(). Because content is read from the fully rendered page, JavaScript-heavy pages work the same as static ones.

Tip

Use the CloakBrowser engine when target pages block plain Playwright sessions — see Browser Engines.

Reachability Before Fetching

Both fetchers also implement CheckReachabilityAsync, which navigates to the URL and reports whether the page loaded without downloading and parsing its full content:

var check = await fetcher.CheckReachabilityAsync("https://test.example.com");
if (!check.Reachable)
{
    // Skip the expensive fetch
}

See URL Reachability for the full contract.

Lifetime

Fetchers implement IAsyncDisposable. When resolved from DI as singletons they are disposed together with the container; when constructed manually, dispose them with await using.