Changelog
Release notes for analog-sdk.
0.17.0 — 2026-07-25
Section titled “0.17.0 — 2026-07-25”Changed
Section titled “Changed”-
Extraction improved on platform status pages and grouped multi-day schedule pages.
-
Markdown now reflects the rendered page only. Content that was not displayed at fetch time — dismissed cookie dialogs, closed drawers and menus, hidden template and variant blocks — no longer appears in any markdown surface (
result.markdown, per-section markdown,-f mdexports). Markdown of template-heavy pages gets substantially smaller, with the visible content untouched; the document title is still included, andassess’s measured token estimate shrinks with it. -
Field schemas follow the page. A section’s
fieldsnow lists its fields in the same order as its records — the page’s own order for comparison and schedule sections, most-relevant-first elsewhere — instead of alphabetically, sodescribeand schema listings read in record order. Saved results keep the order they were saved with.
-
Icon-only controls render what the page declares. A status icon, an icon-drawn button, or an icon-only link whose meaning the page declares in its accessibility tree (
aria-label, SVG<title>) now renders that declared text in markdown — a status page’s component list readsAPM … Operationalinstead of a bare name, and an icon-only link keeps its destination with its declared text instead of disappearing. Visible text always wins over a label,aria-hiddencontent stays silent, and nothing is ever invented — the same contract icon-only table cells already had. -
Markdown discloses values the page draws only as icons. A comparison column whose values exist only as unnamed icons (a checkmark matrix, say) renders blank in any text form — indistinguishable from “no value”. Every markdown the CLI emits (
export -f md, per-section export,get/open --markdown) now carries the same withheld note the records preview shows: the affected columns, and that a clipped screenshot of the region will show them. A per-section markdown export also repeats the preview’s plain withheld-columns line, since its comparison table is built from the records.assess’s comparison guidance now points at the withheld note instead of a blanket “read the page as markdown”. Results without withheld columns are unchanged. -
Links in records resolve against the page that answered. When a fetch is redirected, the document’s relative links — record URL fields, and the pagination disclosure’s next link — now resolve against the URL that actually served the page, not the address you requested. In a
pages=Nsweep, each followed page resolves against its own serving URL, and the sweep’s page list names the pages as served. Previously a page served from another host produced record URLs anchored to the requested host. -
Comparison sections now print as the page authored them. A comparison section — a pricing or edition matrix with few records and many fields — used to preview as one unreadable line per sampled record, and its markdown lost the comparison entirely.
preview()andanalog export -f md --sectionnow render these sections in the page’s authored orientation: features as rows, one column per record (headed by each record’stable_columnvalue), with the page’s own row-group headings preserved.records,fields, and every structured export (json/csv/yaml) are unchanged; ordinary sections keep the record orientation. -
Section ids round-trip.
--section(ondescribe,export,distinct, anddiff) now accepts the id forms results print —structured_content[N]andsection[N]— alongside labels, bare indices, andall. A heading label shared by several sections now selects all of them instead of silently the first. -
Markdown tables now carry the declared text of icon-only cells. A comparison matrix that draws boolean cells as icons (checkmarks) declares their meaning accessibly (
aria-label, SVG<title>); the markdown view now renders those declared words instead of empty cells, so a feature column no longer reads as if no plan offers it. Cells with no declared text anywhere remain empty, andaria-hiddencontent stays silent.
-
Results now name the URL that actually served the page. When a fetch is redirected,
result.resolved_urlcarries the final URL (it isNonewhen you supplied the HTML yourself), and it persists with the saved result, so an agent can cite the source it actually read. When the serving host differs from the requested one — the case that changes a citation — the fetch log says so andanalog historynames the serving URL on that result’s row. The requested URL remains the result’s identity everywhere else. -
Section.locate_in(html)— find a section in a different rendering of its page. A result’s xpaths address the document the extraction read; a live DOM after scripts ran, or a re-fetch, can shift positional paths.locate_infinds the section there by its own record values and returns matches with xpaths valid in the document you passed. One match is a confident location; several mean the page holds several full copies of the content (a duplicate widget, a mobile/desktop double render) — pick with what only you can see, such as which copy is visible. An empty list means the section couldn’t be pinned — never a silent guess at a wrong element. The preview’s visual-withheld hint now points at it for screenshot clips. -
Results now carry the page as Analog read it.
document_viewships the exact document the response’s xpaths address, as a compact verified patch against the HTML you submitted;attach_htmlreconstructs it automatically. Section, outline, and navigation xpaths now resolve reliably on pages where a plain re-parse used to come up empty or silently land on the wrong element — so per-section markdown stops coming back empty on those pages, and markdown no longer includes markup that plays no part in what a reader sees. When the view is absent (an older service) or fails verification, everything degrades to parsing the submitted HTML as-is. Wire schema 24. -
page_sweep.divergent_sections— a multi-page sweep now discloses when a later page or batch contributed a section whose fields matched no section captured earlier: the count arrives inpage_sweep, the affected section carries amerge_notesaying why it stands alone, and the preview adds a sentence warning that no single field spans every merged record. A sweep that fragments is never presented as one uniformly queryable collection.
0.16.1 — 2026-07-23
Section titled “0.16.1 — 2026-07-23”- Pages that fold detail behind in-page disclosure links now report the
available content under
browse_actions;expand_all=Truereveals it before capture. Ordinary navigation links remain untouched.
0.16.0 — 2026-07-23
Section titled “0.16.0 — 2026-07-23”-
Feedback submissions now return a durable receipt.
Client.submit_feedback(...)exposes the opaquereport_id, and bothanalog feedbackcommands print it asReceipt:so a submission can be cited during later triage. The ID is not a report-reading endpoint. -
Built-in browser recipes are now replayable.
Browser.reciperecords every serializable setting that shaped a fetch, andBrowser.from_recipe(...)reconstructs it. New browser-backed saved results retain that recipe infetch_settings.browser_recipe; older saves remain readable and state that the exact recipe is unknown. -
Compatible page areas can now arrive as a
Collection.result.collectionspreserves the physicalSectionindices and identity field while providing one canonical local records view. Repeated editorial placements remain available through the member Sections; Collection records select one whole authored placement and never fuse values across placements. A complete Collection powersresult.records, CSV, YAML, and DataFrame export without duplicating repeated placements. Wire schema 23. -
page_sweep.cross_section_repeats— a multi-page sweep now discloses when the same records appear in more than one section of the merged result (two layouts of one collection that stayed separate sections), matched by a shared per-record URL. The preview adds a sentence when it’s nonzero, so a “duplicates dropped” count is never read as “all duplicates handled.”
Changed
Section titled “Changed”- The serializer family is now methods, matching
to_dataframe():result.to_json(),result.to_yaml(),result.to_csv()replace theresult.json/result.yaml/result.csvproperties. A serialization renders output (to_json()includes the full markdown rendering), so it reads as the call it is — and.jsonno longer collides with Pydantic’s inheritedjson()method, which broke generic Pydantic tooling’s expectations. No compatibility aliases; update call sites by addingto_and parentheses..markdownstays a property: it is the page’s content, cached after first render, not an export.
-
The built-in browser now preserves visible page content rendered inside open web-component boundaries instead of returning an empty host element.
-
Finite virtualized lists no longer lose rows that appear only between the first and final rendered windows during scrolling.
-
load_moreguidance now refers only to content controls. Generic “More” controls in site navigation, headers, footers, menus, and dialogs are no longer offered or clicked. -
Complete static pages no longer report incomplete feed coverage. A
windowed_feeddisclosure now means the browser restored content that the page removed during scrolling. -
Pagination guidance now requires credible evidence that the current collection continues. Unrelated
page=1links and carousel slide counts no longer produce whole-page pagination claims. -
The built-in browser now captures complete collections when a page initially shows only a preview and reveals the rest through an in-page control.
-
Extraction quality improved on complex multi-section pages, with more complete record coverage and more accurate Section boundaries.
-
Comparison results now keep their row and column identities together. Authored blank values are returned as
null, visual-only values are named inwithheld_columns, and comparisons that cannot be preserved as records point to markdown instead. Fit guidance recommends structured comparison only when both axes are named and no comparison fields are withheld. Wire schema 22. -
Transient gateway failures no longer spend daily quota more than once for one extraction. Retries share the logical extraction’s quota accounting without retaining the URL, page content, or result server-side.
-
Pages with a continuously-updating DOM (live clocks, ad slots, client-side hydration) now capture much faster in the built-in browser. Such a page never sits perfectly still, so the pre-extraction scroll pass used to run to its internal cap before giving up; it now recognizes a settled page promptly and captures the same content in a fraction of the time.
-
The first help screen (
analog --help) now shows the recommended one-call Python usage —from analog import analog; analog("https://example.com")— instead of the lower-level hosted client.
0.15.0 — 2026-07-18
Section titled “0.15.0 — 2026-07-18”-
pages=Nnow captures script-driven pagination. In-page batches are merged under the same result contract as link-followed pages.page_sweep.mechanismis"in_page",batches_capturedreports how many batches arrived, andpagination.in_page_controlsdiscloses the available controls. If a control navigates away, captured batches are kept and the stop reason iscontrol_navigated. See the fetching guide. -
pagination.stated_totalreports the page’s own collection count. It is the site’s claim, not Analog’s record count, so both remain visible when they differ. -
Sticky field orders.
analog reorder-fields <ref> FIELD...andanalog.reorder_fields()put named fields first on a saved result and remember the order for later fetches of the same URL.--onceorsticky=Falseapplies it only to the current result; replayed rules appear inapplied_orders. See work with results. -
Comparison tables arrive as one joined section. Compared plans or models are records keyed by
table_column; grouped table fields expose their heading throughFieldInfo.table_group. Wire schema 17. -
assessreportsnavigation_probe. The fit check can show top-level destinations from the already-fetched page before an extraction is spent. See the fit-check guide. -
section.withheld_visualidentifies glyph-only columns. The disclosure names the columns and directs the reader to a clipped screenshot rather than guessing what a glyph means. Wire schema 16. -
Results now carry the page’s navigation and outline.
result.navigationcontains labeled link trees;result.outlinedistinguishes extracted, non-extracted, and structural regions and replacespage_sections. Both appear inpreview()and are searchable withfind(). -
Sections expose
Section.label_url. When a section heading has one unambiguous destination, the absolute URL points to the fuller page; otherwise it remains empty. -
Greenhouse fit checks disclose the board’s public jobs feed. The feed’s own current total is reported as
result.fit.item_count, the provider-neutral replacement forproduct_count.
Changed
Section titled “Changed”-
Uniform multi-page sweeps use less service compute while preserving the same results. Wire schema 19.
-
Outline outcomes are more specific. Empty repeated regions use
no_fields_detectedorno_emittable_fields; overlapping regions useoverlapping_area_extractedand may point to the shipped section throughsuperseded_by. The catch-allnot_selectedis retired. Wire schemas 18, 20, and 21. -
The feedback vocabulary gains
garbled_markdownfor text that returned malformed or out of order. -
Extraction quality improved on script-driven listings, comparison tables, navigation-heavy pages, and table-heavy pages.
-
--load-allreaches a wider range of clearly labeled load-more controls. -
Bot-protection challenges no longer show pagination or fit advice derived from the challenge page.
-
assesspreserves the page’s most prominent navigation destinations when a menu contains many links. -
Automatic browser interactions no longer replace the requested page with a navigated destination. If the captured address still changes, the result discloses both addresses.
-
analog findsearches navigation and outline entries as well as records.--fieldcontinues to restrict the search to records. -
export --fieldsnow rejects unknown fields with the available field names and guidance for heterogeneous sections.
0.14.0 — 2026-07-15
Section titled “0.14.0 — 2026-07-15”analog docs,analog contact. Pointer commands:docsprints the documentation URL (pure output —analog get $(analog docs) --mode localreads the docs in the terminal);contactprints the team email and points atanalog feedbackfor reports that go straight into triage.
Changed
Section titled “Changed”- Analog fetches only public web addresses by default.
getandassessnow decline local and private-network hosts and non-web schemes likefile:, so a page can’t steer a fetch atlocalhost, an internal address, or the local disk. Pass--allow-private(allow_private=True) to reach a dev server or intranet host on purpose. Paginated sweeps follow only links on the page’s own host.
- Signed-out
analog getsays what it’s doing. Without a sign-in,getreturns the page’s markdown (mode=local) — it now says so on stderr and names the fix: runanalog loginfor structured records. Previously the downgrade was silent, and a first run beforelogincould read as “Analog returns prose.” - Numeric columns survive renames and narrowed exports. Renaming a
numeric field (including swaps) keeps its normalized numbers under
the new name, and
export --envelopere-aligns per-record numbers and structural-outlier positions after--where/--sort/--limit/--fields. - Detail toggles inside a card’s own header now expand. With
--expand-all(expand_all=True), per-item disclosure toggles that sit inside a section’s header are recognized and opened, so their detail is captured — previously only toggles outside a header were. - A deactivated account ends with a clear terminal error — the commands name the state and stop, instead of a generic sign-in failure.
- Hardened the fetch and sign-in paths for launch. The site-feed probe streams and size-caps what it downloads, so a hostile server can’t balloon memory; and sign-in, credential handling, and result parsing got a robustness pass.
0.13.0 — 2026-07-11
Section titled “0.13.0 — 2026-07-11”analog help— the subcommand form of--help.analog helpprints the top-level help;analog help getprints exactly whatanalog get --helpprints; nested paths work (analog help feedback quality).-hnow works everywhere as the short form.
Changed
Section titled “Changed”- The feedback label vocabulary is now version 3 — every label
names what you observed in the result (
no_records_found,misfielded_values,page_chrome_in_records,wrong_content_extracted, …). At open launch the vocabulary freezes to additive-only. - Wire schema is now 13.
Section.items_detectedcounts the repeating items the page shows in the section’s area. Results saved by earlier versions reopen unchanged.
0.12.1 — 2026-07-10
Section titled “0.12.1 — 2026-07-10”Paginated collections can be swept —
analog(url, pages=N) (CLI: --pages N) follows the site’s own next
links, politely, capped at 50, and discloses its coverage on
result.page_sweep. Per-item detail toggles can be expanded
(expand_all=True / --expand-all), and long feeds no longer lose
records to scrolling. Also: saved results remember how they were
fetched; virtualized tables disclose the page’s own declared size;
result.rate_limit gains the daily quota; the package ships
py.typed; analog assess mentions a site’s sitemap when robots.txt
lists one; back-to-back extractions got dramatically faster (one warm
browser per process); legacy-encoded pages decode correctly on the
plain-GET path; and a long list of contract, disclosure, and
robustness fixes landed alongside. Extraction quality improved on
discussion threads (records gained a depth field), menu-styled
pages, and multi-paragraph content.
0.12.0 — 2026-07-06
Section titled “0.12.0 — 2026-07-06”analog feedback — quality reports with standardized labels, and
feature requests. Extraction URLs are never logged; a quality report
includes the URL you explicitly submit and never page content.
result.to_dataframe(); filtered history deletion (analog rm --older-than 30d); store disk-usage reporting; partial-coverage
disclosures for paginated pages; the credential moved from the OS
keychain to a local owner-only file (run analog login once after
upgrading); a lighter install; and the fit check reworked around
measured facts and task guidance. Extraction quality improved on
store and listing pages, and field-naming contracts firmed up —
price is always the pay-now price, with price_excl_vat and
review_count beside it where pages show them.
0.11.0 — 2026-07-04
Section titled “0.11.0 — 2026-07-04”result.records; analog find; section-addressable markdown;
field renaming as a library operation; guessed-name and
page-truncation disclosures; withheld-column warnings; documented
exit codes on every command. Extraction quality improved on complex
HTML tables.