Misc

Building Resilient GPAL Workflows

Selectors That Survive the Page

A GPAL selector is not a single CSS string -- it is a strategy chain. You define as many matching approaches as you want; GPAL tries them in order and uses the first element that matches. When a site redesign renames a class, a fallback XPath or text match keeps the workflow alive without a code change. Persistent selectors register a handler once and re-evaluate it automatically on every page interaction for the rest of the session -- the right tool for cookie banners, CAPTCHA intercepts, and any nag that can appear at any time. See The Selector System, Match Criteria & Filtering, Fallback Actions: Automatic Recovery on Error, and Persistent Selectors: Handling Nags and Popups.

// Multi-strategy fallback -- tried in order, first match wins

var price = GPAL.Selector

.WithCSS(".product-price")

.WithXPath("//span[@itemprop='price']")

.WithText("$")

.WithSelectorName("Product Price")

.ToGPALObject();


// Persistent: dismiss a cookie banner for the entire session

var cookieBanner = GPAL.Selector

.WithCSS("#cookie-consent .accept")

.CallIfFound((b, u, els) => {

els[0].Click();

return CallIfStatus.Handled;

})

.ToGPALObject();


GPAL.Browser

.GoTo(url)

.WithPersistentSelector(cookieBanner)

.GetText(price)

.Execute<string>();

NOTE

Register a WithPersistentSelector with a CAPTCHA or block-page selector to catch soft blocks -- pages that return HTTP 200 but deliver a challenge instead of data. CallIfFound fires whenever the element is present, so your workflow can log a warning, pause, or escalate rather than silently extracting garbage.

Extraction That Survives Structural Change

CSS class renames and DOM restructuring are the most common source of silent scraper failures. GetLLMDigest extracts content semantically -- you describe what you want in plain language and the model finds it regardless of how the underlying HTML is structured. This makes LLMDigest the right choice for any field whose CSS path is likely to change. For a more targeted approach, LLMDigestRules.yaml lets you fine-tune extraction rules without touching workflow code. For Next.js and React sites, GetHydratedData pulls structured data directly from the hydration payload, bypassing the DOM entirely. GetPageSource with System.IO.File.WriteAllText gives you a raw HTML archive -- if your extraction logic improves later, you can re-parse historical captures without re-scraping. See LLM-Ready Page Digests and Tuning LLMDigestRules.yaml.

// Selector-based extraction breaks when the

// CSS class is renamed -- a structural change

// on the server silently empties your data.

//

// LLMDigest extracts by meaning, not structure:

LLMDigestResult digest;

GPAL.Browser

.GoTo(url)

.GetLLMDigest(out digest)

.Close();

// digest.Markdown contains structured content

// regardless of how the page HTML is organized.


// Raw HTML capture for re-processing later:

string html;

GPAL.Browser

.GoTo(url)

.GetPageSource(out html)

.Close();

System.IO.File.WriteAllText(archivePath, html);

Identity, Evasion, and Flexible Configuration

StealthType is a bitmask -- you combine only the flags your target actually requires rather than applying everything at once. CDP suppresses automation signals at the DevTools level. GoogleReferrer makes the visit look like a search result click. PatchDriver strips automation markers from the driver binary itself. WithUseAutomationEngine is another resilience lever: if one engine gets blocked, switching to another changes the fingerprint of the session without changing any workflow logic. Beyond evasion, GPAL named-constant structs accept freehand values so configuration is never locked to a fixed set. WaitFor accepts both named WaitTime constants such as Forever and Immediate and any raw millisecond value. WithModel and WithProvider accept both GPAL-defined names and any freehand identifier, so new AI models and providers work without a GPAL update. See Stealth Techniques - Controlling What the Browser Reveals and Named-Constant Structs: An Enum That Also Takes Freehand Values.

// Combine stealth flags as needed

GPAL.Browser

.WithUseStealth(

StealthType.CDP |

StealthType.GoogleReferrer |

StealthType.PatchDriver)

.GoTo(url);


// Swap the automation engine without touching anything else

GPAL.Browser

.WithUseAutomationEngine(AutomationEngine.Puppeteer)

.GoTo(url);


// Named-constant structs accept freehand values:

// WaitTime has named constants and accepts raw ms

GPAL.Browser.GoTo(url).WaitFor(WaitTime.Forever);

GPAL.Browser.GoTo(url).WaitFor(3000);


// AI models are freehand strings -- no update needed

GPAL.AI.WithModel("claude-opus-4-8-20251101");

NOTE

No single technique covers every scenario. A real resilience strategy combines them: a multi-strategy selector for structural drift, a persistent CAPTCHA handler for soft blocks, LLMDigest for fields prone to CSS churn, and the right stealth flags for the target site. GPAL is designed so these layers compose naturally without interfering with each other.

💬 Ask GPAL