# Picking and recording

Point at elements in a live page to get locators and list fields, and record what you do as program steps.

The program builder opens a live browser on the page you are automating, and a copy of any page
your jobs stored. Pick an element on either to get ranked locators and list fields, or use the live
page normally and let Kaabist record what you do as steps.

## When to use it

Pick when you know which values you want and need reliable locators for them, especially lists.
Record when the program has to *do* something first: sign in, fill a form, open a menu. For a page
that only needs reading, picking on a stored page is the fastest: nothing runs and it costs
nothing.

## The browser pane

**Browser**, in the builder's right column, shows the live page with a toolbar above it: a
**Navigate** / **Pick** switch, back, reload, the address bar, and **Open browser** (which becomes
**Close** once it is open). Before you open it you can name a stored session to start signed in;
the pane says which network the browser goes out through, the same as a run of the program.
Presets set the viewport (desktop 1280×800, small laptop, tablet, mobile), and **Use for program**
copies the current one into the program's options. Tabs appear when the page opens more than one;
"Something covers the page" warns about an overlay.

It has two modes:

- **Navigate**: you use the page as usual, and Kaabist records what you do as steps.
- **Pick**: clicks no longer reach the page; they select elements instead.

## Picking

Press **Pick** next to a target or a field in the step list: a banner says "Pick mode: click the
element in the page". Hover to see what is under the pointer, outlined on the page; click to
select it, and the target or field is filled in. A label beside the selection names the element,
its best locator and how many similar elements the page has.

Every selection comes with up to six locators, best first, each checked to match exactly that
element: a test id or an accessible role and name when the page has one, an id, the element's text,
a CSS selector built only from classes that look stable, and finally a structural path. Elements
inside shadow roots get a `>>>` selector that names the host chain; elements inside iframes carry
their frame path.

| Key | Moves the selection to… |
|---|---|
| ↑ / ↓ | the parent / the first child |
| ← / → | the previous / next sibling |
| `s` | every similar item: the whole list |
| `r` | text-range mode: select characters inside the element to build a `regex` field |
| `Esc` | nothing (clears the selection) |

In the step's form, the target's locators are listed best first, each marked *stable*, *fair* or
*fragile* and *unique* or with its number of matches; reorder, remove or add one by hand.

**Lists.** Press `s` on one price in a grid and the selection becomes a list: the item selector,
how many items there are, and the path from an item to the price. Pick anything else inside an item
afterwards and it is added as a field of that list, with a suggested name and a few sample values.
When a list renders fewer rows than it claims to have, the selection says so (`virtualized`): that
list needs a `scroll` step to extract fully.

**Hover-only UI.** Open the menu in navigate mode, then switch to pick mode: the pointer no longer
reaches the page, so the menu stays open. *Freeze* additionally pauses animations. `Ctrl+click` in
navigate mode picks without switching modes.

**Ground truth.** When you confirm a field on a page, Kaabist stores a snapshot of the page and the
element's fingerprint as the field's *ground truth*: the reference self-healing uses when the page
changes (see [self-healing](https://docs.kaab.ist/concepts/self-healing)).

## Picking on a stored page

You do not need a live browser to write an extract schema. **Stored page** opens any page your jobs
have already fetched: type a reference such as `job_…:steps[2]` and **Open**, choose the version's
ground truth, or press **Use this page in the picker** on a step of a test run. You pick on the copy
Kaabist stored, the same way as live: the same locators, the same keys, the same lists and fields,
because it is the same picker running over the same page. It is instant, since nothing goes back to
a browser, and it costs nothing.

What you see is a safe copy: scripts and anything else that could run are removed, and the copy is
shown in a sandbox where nothing can run anyway, so links do not navigate and forms do not submit.
Images and styles are loaded as the page had them. Frames the page had on its own site are shown
too; frames from other sites stay empty.

**Text ranges.** Select characters with the mouse and press `r`: the selection becomes a `regex`
field. Press `r` with nothing selected to see the element's whole text instead.

**Testing a schema.** While you edit, every field is extracted from the page in your browser as you
type; **Run here** shows the result under "In the browser". **Test on the server** runs the schema
against the stored page on Kaabist, under "On the server": the answer a job would give for that
page, including fields that read embedded JSON or a captured API response, which only the server
has.

## Recording

Press **Record** in the browser pane; it counts the steps it has recorded and **Pause recording**
stops it. In navigate mode every click, every field you type into, every selection in a dropdown and
every checkbox becomes a step, with locators for the element. Typing into a field is one `fill`,
however many keys it took.

The recorder makes suggestions on the steps it adds:

- **A password** is never recorded. The step says "The value typed here is a secret; it is not
  recorded." and offers to declare a `secret` input; the step then uses `{{inputs.password}}`.
- **A one-time code** is recognised ("This looks like a one-time code.") and **Ask for it when the
  program runs** adds an `await_input` step; the fill then uses `{{vars.otp}}`.
- **After an action that navigates**, "Add expect:" offers conditions (the new URL, headings or
  forms that appeared) that you attach with one click.

The recorder's steps are ordinary program steps (marked `x_kaab: { "source": "recorder" }`), so
everything else in the builder (editing, linting, testing) works on them unchanged.

## Worked example

Record a customer portal's sign-in with a one-time code and pick its report:

1. In a new program's builder, open **Browser** on `https://portal.example.com/login`, press
   **Open browser**, then **Record**.
2. Sign in with a test account and accept the suggestion to declare the password as a secret
   input.
3. Type the one-time code the site sent and accept **Ask for it when the program runs**. Open the
   report, and attach the suggested `expect` on its URL.
4. **Pause recording**. Add an **Extract** step, press **Pick** on a new field, and click one amount
   in the report table; press `s` to select every row. Pick the other columns of a row to add them
   as fields of the list.
5. In **Test**, **Run all**: the run stops to ask for the one-time code, then returns the report's
   40 rows.

## Pitfalls

- **Picking in navigate mode.** Clicks reach the page and get recorded. Switch to **Pick** first,
  or use `Ctrl+click`.
- **Accepting a fragile locator.** If the best candidate is marked *fragile*, add a better one by
  hand (a test id or a role and name) before you publish.
- **Typing a real password while recording.** It is not recorded, but it does reach the site. Use a
  test account.
- **A virtualized list without a `scroll` step.** The extract returns only the rows the page had in
  the DOM.

## Reference

- [Targets](https://docs.kaab.ist/reference/dsl/targets) and [locators](https://docs.kaab.ist/concepts/locators)
- [Extract fields](https://docs.kaab.ist/reference/dsl/actions/extract), [`regex`](https://docs.kaab.ist/reference/dsl/fields/regex),
  [`many`](https://docs.kaab.ist/reference/dsl/fields/many)
- [`await_input`](https://docs.kaab.ist/reference/dsl/actions/await-input)
