Why does `WaitForSelectorAsync` in PuppeteerSharp fail to find an element by ID?

I’m using PuppeteerSharp to automate Google Maps and want to click the “Ich stimme zu” button with ID introAgreeButton. However, await page.WaitForSelectorAsync("#introAgreeButton") times out after 30 seconds even though the element exists in the HTML. I tried adding WaitForNavigationAsync() and delays, but it still fails. How can I reliably detect and interact with this element using WaitForSelectorAsync?

Often the issue isn’t that the element doesn’t exist, but that it’s inside an iframe or loaded dynamically after scripts run. Try this pattern:

// Wait for the element to appear and be visible
var button = await page.WaitForSelectorAsync("#introAgreeButton", new WaitForSelectorOptions
{
    Visible = true,
    Timeout = 60000 // increase timeout
});

await button.ClickAsync();

If the button is inside an iframe, you need to first get the frame:

var frame = page.Frames.FirstOrDefault(f => f.Url.Contains("google.com/maps"));
var button = await frame.WaitForSelectorAsync("#introAgreeButton", new WaitForSelectorOptions { Visible = true });
await button.ClickAsync();

Dynamic content often delays rendering, so make sure you’re waiting for visibility and not just presence in the DOM.

Sometimes IDs appear in the DOM but aren’t interactable yet. You can try directly evaluating JavaScript to click it:

await page.EvaluateFunctionAsync(@"() => {
    const btn = document.querySelector('#introAgreeButton');
    if (btn) btn.click();
}");

This approach bypasses PuppeteerSharp’s waiting and can handle situations where the element is quickly added and removed or temporarily obscured.

Google Maps often loads content via AJAX. Using WaitForNavigationAsync() alone may not be enough because the page doesn’t “navigate” in the traditional sense. Try:

await page.GoToAsync("https://www.google.com/maps", WaitUntilNavigation.Networkidle0);
var button = await page.WaitForSelectorAsync("#introAgreeButton", new WaitForSelectorOptions { Visible = true });
await button.ClickAsync();

The key is Networkidle0, which waits for all network requests to finish, increasing the chance that dynamic elements are present when you search for them.