# Working with results

Source: https://getanalog.io/docs/results/

Reopen a saved page, find what matters, export records, and compare changes.

By default, a structured result is saved locally under a **handle** like
`20260719-k7m2p9`. A handle identifies one result as the page looked
when you fetched it. Use `latest` anywhere a command expects a handle
to work with the newest one.

The examples below follow one page of quotes, saved as `quotes-before`.
They assume you have [installed Analog](https://getanalog.io/docs/install/) and
[signed in](https://getanalog.io/docs/authenticate/).

<details class="reference-index">
<summary>On this page</summary>

- [Key terms](https://getanalog.io/docs/results/#key-terms)
- [Start with the page map](https://getanalog.io/docs/results/#start-with-the-page-map)
- [Inspect and find](https://getanalog.io/docs/results/#inspect-and-find)
- [Export the records you need](https://getanalog.io/docs/results/#export-the-records-you-need)
- [Compare two saves](https://getanalog.io/docs/results/#compare-two-saves)
- [Choose the right Python view](https://getanalog.io/docs/results/#choose-the-right-python-view)
- [Manage saved results](https://getanalog.io/docs/results/#manage-saved-results)
- [Exit codes](https://getanalog.io/docs/results/#exit-codes)

</details>

## Key terms

<dl class="result-concepts">
<dt>Saved result</dt>
<dd>

The locally stored output of a run, available without fetching again.

CLI: [`analog view --json`](https://getanalog.io/docs/cli-reference/#analog-view).
Python: [`results.open()`](https://getanalog.io/docs/api-reference/#open).
MCP: [`analog_open`](https://getanalog.io/docs/mcp-reference/#analog_open).

</dd>
<dt>Handle</dt>
<dd>

The identifier used to reopen a saved result. Friendly names and `latest`
also work as references.

CLI: [`analog history`](https://getanalog.io/docs/cli-reference/#analog-history).
Python: [`results.history()`](https://getanalog.io/docs/api-reference/#history).
MCP: [`analog_history`](https://getanalog.io/docs/mcp-reference/#analog_history).

</dd>
<dt>Preview</dt>
<dd>

A compact overview of sections and their fields, including types and
sparse-field coverage. The saved records remain available in full.

CLI: [`analog view`](https://getanalog.io/docs/cli-reference/#analog-view).
Python: [`result.preview()`](https://getanalog.io/docs/api-reference/#analogresponsepreview).
MCP: [`analog_describe`](https://getanalog.io/docs/mcp-reference/#analog_describe).

</dd>
<dt>Record</dt>
<dd>

One mapping of field names to extracted values, such as a product or review.

Read `section.records` or `collection.records`, or
[export selected records](https://getanalog.io/docs/results/#export-the-records-you-need).

</dd>
<dt>Record section</dt>
<dd>

A group of extracted records with field metadata and page-location information.

CLI: [`analog export --section`](https://getanalog.io/docs/cli-reference/#analog-export).
Python: [`result.structured_content`](https://getanalog.io/docs/results/#choose-the-right-python-view).
MCP: [`analog_section`](https://getanalog.io/docs/mcp-reference/#analog_section).

</dd>
<dt>Collection</dt>
<dd>

Compatible record sections viewed as one dataset, with repeated identities
represented once and the source sections retained.

CLI: [`analog export --collection`](https://getanalog.io/docs/cli-reference/#analog-export).
Python: [`result.collections`](https://getanalog.io/docs/results/#choose-the-right-python-view).
MCP: [`analog_collection`](https://getanalog.io/docs/mcp-reference/#analog_collection).

</dd>
</dl>

In Python, `result.sections` includes record and Markdown sections together
in page order. `result.structured_content` contains only record sections,
so their indices are not interchangeable. MCP's `analog_section` uses
the index in `structured_content`.



## Start with the page map

Fetch the quotes page and give the saved result a friendly name.
The rest of this guide uses `quotes-before` so another fetch will not
change which result you are reading.

Reopening a result does not fetch the page again. The
preview keeps the page in reading order: each record section shows its
label, record count, and field metadata. Markdown regions show their available
labels, roles, and rendered sizes; their text remains in the Markdown view.
Prose and navigation remain in their original positions, while printed
`section[N]` identifiers keep their record indices. Coverage notes say when
the saved result contains only part of what the page offered.

In Python, `result.preview()` provides the same orientation view. Over MCP,
[`analog_describe`](https://getanalog.io/docs/mcp-reference/#analog_describe) returns the preview;
[`analog_open`](https://getanalog.io/docs/mcp-reference/#analog_open) returns the full saved result.



### Save the example page

```bash wrap=true example=illustrative fragment=true
analog browse https://quotes.toscrape.com/js/
analog rename latest quotes-before
```

This saves the first page of quotes. If you already use the name
`quotes-before`, choose another name and use it throughout the examples.

### Return to the page map

```bash example=illustrative fragment=true
analog view quotes-before
```

### Read the whole saved page

```bash wrap=true example=illustrative fragment=true
analog view quotes-before --markdown
```





## Inspect and find

Check the section numbers and field names before searching or exporting.
In this example, `section[0]` contains the quotes: `text` holds the quote,
`text_2` holds the author, and `tags` holds its topics. The other sections
contain navigation links.

`describe` reports each section's fields, coverage, distinct-value
counts, and samples. `view --find` searches records, prose, and page regions
in reading order; navigation links are records too, so they are
searchable. `distinct` counts the values in one field. Add `--field`
to `view --find` when you want to search only one field.



### Check the fields

```bash example=illustrative fragment=true
analog describe quotes-before
```

Use the names reported by your result if the page has changed.

### Find quotes by Einstein

```bash wrap=true example=illustrative fragment=true
analog view quotes-before --find "Einstein" --field text_2
```

### Count the topics

```bash example=illustrative fragment=true
analog distinct quotes-before tags
```





## Export the records you need

Select the quotes section so the export contains quotes without the
page's navigation links. Then choose the fields and rows you need.

`--section` accepts the displayed section number or label. Omit it
when the result contains one dataset, or several sections that can be
safely combined. Choose `json`, `csv`, `yaml`, or `md`. You can also
select fields, filter rows, sort, and limit the output. Here, `~` matches
text containing `Einstein` in the author field.

Numeric filters and sorting use the underlying number while exports
keep the page's display value, such as `"from $5.41"`. Use `--section`,
`--kind`, or `--collection` when you want records from one part of a
page rather than every compatible record.



### Export the quotes as CSV

```bash wrap=true example=illustrative fragment=true
analog export quotes-before -f csv --section 0
```

### Select two quotes by Einstein

```bash wrap=true example=illustrative fragment=true
analog export quotes-before -f csv --section 0 \
  --fields text_2,text --where "text_2~Einstein" \
  --sort text --limit 2
```

The CSV contains the author and quote columns, sorted by quote text.
Add `--output quotes.csv` to write it to a file.

### Carry context into another session

JSON `export` and `describe` support `--context none|compact|full`:

- `none` (default) returns the selected records or statistics as an array.
- `compact` carries that data with its source, applied selection, and
  qualifications in one object, without page Markdown.
- `full` keeps the compact object and adds the original saved artifact under
  `context`, including its schemas, section relationships, and Markdown.

The selected data stays identical. Full context can include unselected page
content; it describes the saved source, not a guarantee of capture completeness.
Ordinary exports keep their requested format and report
applicable qualifications on stderr. An exported CSV alone does not carry
those qualifications; use the contextual JSON when the next reader needs
them. See [Export with context](https://getanalog.io/docs/cli-reference/#analog-export).





## Compare two saves

Keep the earlier result before fetching again. The name `quotes-before`
still refers to the result saved at the start of this guide; after the
next fetch, `latest` refers to the new one.

`diff` compares corresponding sections and reports record turnover,
fields or sections that appeared or disappeared, count changes, and
changes in field coverage. The comparison itself is local and does not
fetch either result again. Use `--section` or `--kind` to narrow it.



### Fetch again and compare

```bash wrap=true example=illustrative fragment=true
analog browse https://quotes.toscrape.com/js/
analog diff quotes-before latest
```

If the page has not changed, the comparison may show no differences.
You can also compare two handles from `analog history`.





## Choose the right Python view

The object returned by `analog()` and one reopened with
`results.open()` offer the same views. Reopen `quotes-before` to continue
with the same saved page in Python, without another fetch.

`section.records` and `collection.records` contain the records within a
chosen section or collection. `result.records` is the simplest view when
the page contains one dataset, or several sections Analog can safely
combine. If the page contains different kinds of records, it raises an
error rather than flattening them into one misleading list.

The quotes and navigation have different fields, so this example reads
the quote records from `result.structured_content[0]`.



### Read the saved quotes in Python

```python example=illustrative fragment=true
from analog import results

result = results.open("quotes-before")
quotes = result.structured_content[0]
print(quotes.records[:3])
```

Run this on the same machine and with the same local store as the CLI
examples. Python accepts friendly names too.

### Read just the quote text

```python example=illustrative fragment=true
for quote in quotes.records:
    print(quote["text"])
```

Use the field names from `analog describe` to select other values.
For tabular work, `quotes.to_dataframe()` returns a pandas DataFrame
when the optional pandas dependency is installed.



### Keep the context you need

Use the view that matches the question:

- **`result.structured_content`** contains the physical record
  sections in page order. Select one by heading with
  `result.section(label)`, or every section of a kind with
  `result.sections_by_kind(kind)`.
- **`result.sections`** keeps record sections and prose together in
  the page's reading order. Use it when placement or surrounding text
  matters.
- **`result.collections`** combines compatible sections when the same
  entities appear in several places. A collection provides one record
  per identity while retaining the source sections and placements.
- **`result.outline`** shows the page regions Analog found and whether
  each became records, remained page context, or was not extracted.
  Use it to distinguish content that was absent from content that was
  present but not returned as records.

Whole-result exports include `result.to_json()`, `result.to_yaml()`, and
`result.to_csv()`. YAML and CSV follow the same compatibility rules as
`result.records`; use the CLI's `--section` option to export the quotes
section directly as CSV.

Exact attributes, parameters, and return types are in the
[Python API reference](https://getanalog.io/docs/api-reference/).





## Manage saved results

`history` lists saved results newest first with their handles, source
URLs, ages, and record counts. A friendly name works anywhere a handle
does. You gave this guide's result a name at the start; you can change it
later without changing the saved data.

Use `--dry-run` before deleting a group of results by age or URL.

Saved artifacts contain the structured records, ordered Markdown
regions, and page Markdown, never raw HTML. `analog history --usage`
shows their disk footprint. The store is size-bounded and evicts the
least recently opened results first; `ANALOG_CACHE_DIR` overrides the
system cache location.



### Find earlier results

```bash example=illustrative fragment=true
analog history
```

### Change the friendly name

```bash wrap=true example=illustrative fragment=true
analog rename quotes-before saved-quotes
```

After this command, use `saved-quotes` wherever the earlier examples use
`quotes-before`.

### Preview a cleanup

```bash wrap=true example=illustrative fragment=true
analog rm --older-than 30d --dry-run
```

This lists the matching results without deleting them.



## Exit codes

All commands use the same categories so scripts can branch on `$?`:
`0` success, `1` command error, `2` usage, `3` auth, `4` backend
unreachable, `5` fetch refused/failed (including robots.txt refusals),
`6` extraction failed, `130` interrupted.

For `browse`, reaching the requested page limit or the normal end of pagination
is success. An abnormal sweep stop returns its failure category and identifies
any saved partial capture. A requested save that cannot produce a readable
artifact returns a command error. If an explicit `--json` or `--markdown`
result is available, stdout still carries that data; stderr reports the
acquisition outcome. An interruption identifies a partial handle only when
that saved result is available.

Local `view`, `export`, and `describe` return success when the requested local
operation succeeds, including when the saved capture is partial. Capture
limitations remain visible; success does not establish complete site coverage.
Invalid selections, unreadable saves, and failed writes still fail. `view`
of a supplied page file performs acquisition and retains extraction/save
failure status.