Skip to content
Back to skills

External Site Profile Learning

ASecurity

Use this skill when investigating, adding, validating, or debugging external website profiles for the 99idea Playwright browser demo. It teaches how to probe selectors, classify failure modes, add config-driven profiles, and validate both heuristic and Gemini flows.

  • 17 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 30, 2026
testingpythongoshellnodedebugginggitapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned May 30, 2026

npx -y skills add gabrielmoreira/agent-skills-mirror --skill external-site-profile-learning --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of External Site Profile Learning?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for External Site Profile Learning
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/gabrielmoreira-external-site-profile-learning/badge)](https://www.skillsdirectory.com/skills/gabrielmoreira-external-site-profile-learning)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: external-site-profile-learning
description: Use this skill when investigating, adding, validating, or debugging external website profiles for the 99idea Playwright browser demo. It teaches how to probe selectors, classify failure modes, add config-driven profiles, and validate both heuristic and Gemini flows.
license: Proprietary session artifact for local Copilot use
---

# External site profile learning skill

Use this skill when working on the target Playwright browser project (for example, the `99idea` demo project).

This project is a Playwright-based browser demo that supports config-driven external site profiles through:

- `scenarios\site-profiles.json`
- `src\site-profiles.js`
- `src\planner.js`
- `src\llm-planner.js`
- `src\run-demo.js`

## What this skill is for

Use this skill when the task involves any of the following:

- adding a new external site profile
- debugging why an external site passes heuristics but fails with Gemini
- turning a random website experiment into a stable config-driven profile
- identifying whether a site is suitable for the default regression matrix
- distinguishing selector problems from login, anti-bot, or hidden-UI problems

## Core rules

1. Prefer **URL** or **title** verification for external sites whenever possible.
2. Prefer **stable, unique selectors** over generic selectors like `button` or `[name="q"]`.
3. If a site profile exists, the final plan should use the profile's **exact** `searchInputSelector` and `submitSelector`.
4. Keep GitHub out of the default regression matrix. It works, but repeated probing can trigger rate limits.
5. **Classify the site's execution tier before writing a browser profile:**
   - If opencli already supports the site, prefer an opencli-based workflow over a selector-based profile
   - If the site has a public API, prefer fetch over browser automation
   - Only write a browser profile when no higher-tier execution path exists
6. Treat these as different failure classes:
   - selector ambiguity
   - hidden or disabled controls
   - opener-required search UI
   - SPA shell (no usable DOM without full JS rendering)
   - login gates
   - anti-bot / rate-limit behavior
   - heavy pages that stall on `load`

### Dual-engine awareness (inspired by opencli)

When stabilizing a site, consider whether the profile should be:

- **Data-only (YAML-like)**: selector + verification config in JSON — for traditional DOM-based sites
- **Runtime-aware**: includes execution path recommendation (opencli / fetch / browser) — for modern platforms

A good profile should record not just *how to interact with the UI*, but also *what the best execution path is*.

## Standard workflow

### 1. Probe the site

Open the homepage in Playwright and inspect:

- search inputs
- submit buttons
- search opener buttons or icons
- whether inputs are visible, enabled, and editable
- whether there are duplicate controls in headers, footers, drawers, or overlays

Record:

- selector candidates
- whether search is immediately usable
- whether search is hidden/disabled until another action happens
- whether the site supports a deterministic URL check after search

### 2. Classify the site

Use this decision process:

- If a visible input and a stable submit control exist, the site is a good normal profile candidate.
- If the site requires an opener interaction but still fits the current action model, prefer a more specific selector strategy or a special-case scenario.
- If the site requires behavior beyond the current action model, mark it blocked or incomplete rather than forcing a brittle profile.
- If the site is gated by login or aggressively rate-limited, do not add it to the default regression matrix.

### 3. Add the profile

When the site is a good fit, add a data-only profile to `scenarios\site-profiles.json` with:

- `name`
- `hostnames`
- `searchInputSelector`
- `submitSelector`
- `verificationMode`
- `expectedUrlTemplate` when URL verification is available
- `executionTier` — recommended execution path: `opencli`, `fetch`, or `browser`
- `opencliCommand` — if opencli supports it, the exact command template
- `authLevel` — `PUBLIC`, `COOKIE`, `HEADER`, or `LOGIN-GATED`

Keep the behavior in code and the site data in JSON.

Recommended profile-writing rules:

- use exact selectors, not broad selectors that only happen to work once
- qualify selectors with a container when header and footer controls are duplicated
- prefer `verificationMode: "url"` when the site has a deterministic query string
- prefer `verificationMode: "title"` when the search result page has a stable title change
- do not force opener-only or login-gated flows into a normal default profile

### 4. Validate both planning modes

Validate in this order:

1. Heuristic run
2. Gemini / LLM run

Use commands like:

```powershell
npm run validate:external:core
npm run validate:external:popup
npm run validate:external:heavy
npm run validate:external
npm run validate:external:llm:core
npm run validate:external:llm:popup
npm run validate:external:llm:heavy
npm run validate:external:llm
node src\run-demo.js --allow-external --url "https://example.com/" --goal "Search Example for AI and verify that the URL includes q=AI."
node src\run-demo.js --scenario <temp-scenario.json> --planner llm
```

Before Gemini validation, ensure:

- `GEMINI_API_KEY` is available
- `BROWSER_USE_LLM_PROVIDER=gemini`

If the site hangs on full load, use a temporary scenario with:

- `waitUntil: "domcontentloaded"`
- `postNavigationLoadState: "domcontentloaded"`

### 5. Record the failure mode if it does not fit

Use these interpretations:

- **strict mode violation / multiple matches**  
  The selector is too broad. Add a stronger container-qualified selector.

- **timeout waiting for visible or editable**  
  The control is hidden, disabled, off-screen, or not opened yet.

- **type succeeds but Enter does not navigate**  
  The site likely needs a specific submit control instead of Enter.

- **works only with a special opener path**  
  Consider a special scenario instead of a default profile.

- **rate limit / anti-bot / login gate**  
  Do not force it into the stable regression matrix.

## Known good profiles

These are already proven patterns in this project:

### Wikipedia

- input: `#searchInput`
- submit: `#search-form button[type="submit"]`
- verification: title

### Python.org

- input: `#id-search-field`
- submit: `#submit`
- verification: URL contains `q={searchTerm}`

### arXiv

- input: `form.mini-search input[name="query"]`
- submit: `form.mini-search button`
- verification: URL contains `query={searchTerm}`

### YouTube

- input: `input[name="search_query"]`
- submit: `button.ytSearchboxComponentSearchButton`
- verification: URL contains `search_query={searchTerm}`

### CNN

- input: `#pageFooter input[name="q"]`
- submit: `#pageFooter button.search-bar__submit`
- verification: URL contains `q={searchTerm}`
- runtime hint: prefer `domcontentloaded` because the homepage may stall on full `load`

### Bilibili

- input: `#nav-searchform input.nav-search-input`
- submit: `#nav-searchform .nav-search-btn`
- verification: URL contains `keyword={searchTerm}`
- runtime hint: the search flow opens a popup / new tab, so popup following must remain enabled in the runner

## Special case

### GitHub

GitHub works through the search palette, but repeated probing can trigger secondary rate limits.

Recommended pattern:

1. click `button[aria-label="Search or jump to…"]`
2. type into `#query-builder-test`
3. press `Enter`
4. verify URL contains `q={searchTerm}`

Do not treat GitHub as a normal default regression target.

## Blocked or incomplete sites

### BBC

- current state: blocked
- reason: the discovered input is hidden and disabled until additional UI state changes occur

### Tencent News

- current state: blocked
- reason: the homepage shows a search button but no directly usable search input in the default state

### Zhihu

- current state: blocked
- reason: homepage flow goes through sign-in, so anonymous search is not a clean default regression target

## Implementation notes for future agents

- When a profile exists, normalize LLM-generated `type` and `click` steps back to the exact profile selectors.
- If a site has duplicate header/footer search controls, prefer container-qualified selectors.
- If an external site is flaky under full page load, fix the runtime first before assuming the selectors are wrong.
- Keep default validation conservative. A smaller stable matrix is better than a noisy one.
- Use grouped validation runs to isolate profile regressions by class: `core`, `popup`, and `heavy`.
- For each validation report, include concrete evidence (URL/title signal, selector used, and whether popup switching occurred).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.