Skip to content

Changelog

Release notes for analog-sdk.

  • 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.”
  • The serializer family is now methods, matching to_dataframe(): result.to_json(), result.to_yaml(), result.to_csv() replace the result.json / result.yaml / result.csv properties. A serialization renders output (to_json() includes the full markdown rendering), so it reads as the call it is — and .json no longer collides with Pydantic’s inherited json() method, which broke generic Pydantic tooling’s expectations. No compatibility aliases; update call sites by adding to_ and parentheses. .markdown stays a property: it is the page’s content, cached after first render, not an export.
  • 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.

  • pages=N now captures script-driven pagination. In-page batches are merged under the same result contract as link-followed pages. page_sweep.mechanism is "in_page", batches_captured reports how many batches arrived, and pagination.in_page_controls discloses the available controls. If a control navigates away, captured batches are kept and the stop reason is control_navigated. See the fetching guide.

  • pagination.stated_total reports 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... and analog.reorder_fields() put named fields first on a saved result and remember the order for later fetches of the same URL. --once or sticky=False applies it only to the current result; replayed rules appear in applied_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 through FieldInfo.table_group. Wire schema 17.

  • assess reports navigation_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_visual identifies 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.navigation contains labeled link trees; result.outline distinguishes extracted, non-extracted, and structural regions and replaces page_sections. Both appear in preview() and are searchable with find().

  • 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 for product_count.

  • 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_detected or no_emittable_fields; overlapping regions use overlapping_area_extracted and may point to the shipped section through superseded_by. The catch-all not_selected is retired. Wire schemas 18, 20, and 21.

  • The feedback vocabulary gains garbled_markdown for 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-all reaches a wider range of clearly labeled load-more controls.

  • Bot-protection challenges no longer show pagination or fit advice derived from the challenge page.

  • assess preserves 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 find searches navigation and outline entries as well as records. --field continues to restrict the search to records.

  • export --fields now rejects unknown fields with the available field names and guidance for heterogeneous sections.

  • analog docs, analog readme, analog contact. Pointer commands: docs and readme print the documentation and about-page URLs (pure output — analog get $(analog docs) --mode local reads the docs in the terminal); contact prints the team email and points at analog feedback for reports that go straight into triage.
  • Analog fetches only public web addresses by default. get and assess now decline local and private-network hosts and non-web schemes like file:, so a page can’t steer a fetch at localhost, 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 get says what it’s doing. Without a sign-in, get returns the page’s markdown (mode=local) — it now says so on stderr and names the fix: run analog login for structured records. Previously the downgrade was silent, and a first run before login could 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 --envelope re-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.
  • analog help — the subcommand form of --help. analog help prints the top-level help; analog help get prints exactly what analog get --help prints; nested paths work (analog help feedback quality). -h now works everywhere as the short form.
  • 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_detected counts the repeating items the page shows in the section’s area. Results saved by earlier versions reopen unchanged.

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.

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.

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.