## TL;DR
The page renders seat counts with JavaScript after load, so the scraper read an empty shell. Wait for the count element explicitly, fix session handling if login is involved, and prefer the vendor's API or export over scraping wherever one exists.

```text
license agent's scraper failed on SaaS billing page, seat counts came back empty
```

## Use this when
- A scraper returns empty seat counts from a billing page.
- The raw HTML lacks the numbers visible in a browser.
- The scrape worked before a site redesign.

## Not for this skill when
- The page blocks automation. Use the sanctioned API or export path.
- Login fails. Fix the login step first.
- The numbers are present but wrong. That is a selector problem.

## Steps
1. Check whether the count appears in the raw HTML. Verify: you know if it is JS-rendered.
2. Wait for the specific count element before reading. Verify: the element is present.
3. If the page needs a login session, fix session handling first. Verify: the session is valid.
4. Prefer the vendor API or scheduled export when available. Verify: the sanctioned path returns data.
5. Confirm non-empty, sane counts. Verify: the numbers reconcile with the billing total.

## Variant phrasings
### scraper empty results
The symptom-first phrasing.
### billing page scrape failed
The action-first search.
### seat counts empty
The state-first phrasing.

Compatibility: Any browser automation scraping SaaS billing pages.

## Why it happens
Billing pages are single-page apps. Scrapers that read the DOM immediately get the loading shell, and the counts arrive seconds later via API calls the scraper never waited for.

## Edge cases / pitfalls
- Counts loading only after scrolling; scroll the element into view.
- Anti-bot measures serving empty pages to automation; do not evade, switch to the API.
- Selectors changing on redesign; prefer text-based or role-based selectors.
- The session expiring mid-scrape and redirecting to login; detect the redirect.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_X9s6XVtJ6gNEGAb_CKb7Wg
