# Changelog of Allabolag Scraper - Swedish Company Data (`redomic/allabolag-company-scraper`) Actor

- **URL**: https://apify.com/redomic/allabolag-company-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/redomic/allabolag-company-scraper.md

## Changelog

### 0.1 - 2026-11-16 (ownership and linked companies)

- Add `shareholders` and `relatedCompanies` fields, included when available, for ownership and linked-company context.

### 0.1 - 2026-11-15 (company signals)

- Parse `companyDescription` from `purpose` when `description` is missing, and add `estimatedTurnover`, `turnoverYear`, `gazelle` and `mortgages` fields end to end (parser, enriched search/detail/monitor output, monitor fingerprints, dataset overview and README). Fields are included when available.

### 0.1 - 2026-11-15 (README)

- Rewrite README as a buyer-facing sales page: remove internal test/reliability jargon and file references while keeping use cases, real output, and pricing clear.

### 0.1 - 2026-11-15 (DAY-UPDATE)

- Privacy: drop `orgNumber` on sole-trader (enskild firma) rows because it is the owner's personnummer (GDPR), while keeping `orgNumber` for legal entities.
- Search/sort: keyword searches (including sorted ones) use the paginated `companies` block so server-side sort order and range-filtered queries return rows.
- Qualification: add fixture-backed coverage for SNI-code revenue + employee/revenue range filtering returning in-range rows.

### 0.1 - 2026-11-14 (clean dataset)

- The dataset holds company rows only: per-input status rows and the run summary move to the run's key-value store (`STATUS`), so a run no longer ends with two blank rows.

### 0.1 - 2026-11-14 (SNI)

- Add `sniCodes`: list every company registered under SNI 2025 industry codes (`62`, `62.10`, `62.201`, `J`) from allabolag's segmentation register, narrowed server-side by `county`/`municipality` and ordered by `sort`; fixture-backed test over two live pages; battery runs an SNI query. `sniPrimaryOnly` (default on) keeps companies whose main code is one asked for.

### 0.1 - 2026-11-14

- Add `activeOnly` filter to keep only companies with registry status `ACTIVE` in search, detail and monitor flows (inactive/dissolved companies excluded), with schema/docs and fixture-backed tests.

### 0.1 - 2026-11-13

- Overview: parse/emit `postalCode`, `postPlace`, `companyDescription`, and year-over-year `revenueGrowthPct`/`profitGrowthPct` (latest vs prior filed year) from company pages, and remove columns without fixture-backed values (`statusRemarks`, `riskFlags`) plus control columns from the overview view so every remaining overview column is filled in >=1 fixture row.
- Fix server-side sort for non-relevance searches (use paginated companies block so `sort` is honored) and document/verify revenue/employee range filters with fixture-backed Stockholm 10–50 employee coverage; battery exercises sort and range queries.
- Add ICP prospect-qualification filters (`minRevenueKSEK`, `maxRevenueKSEK`, `minEmployees`, `maxEmployees`, `minEquityRatio`, `minRevenueGrowthPct`) applied to enriched/detail rows before output/billing, and compute `revenueGrowthPct`/`profitGrowthPct` from the latest vs prior filed fiscal year (omitted with <2 years). Rows missing a set filter value are dropped; unfiltered/monitor/diagnostic behavior unchanged.
- Add nullable `postalCode` and `postPlace` fields end to end: parsed from postal/visitor address data on detail and search/feed rows when present (omitted when absent), merged into enriched search/detail/monitor output and monitor fingerprints, and documented in dataset schema and README with fixture-backed coverage.
- Rework README to be use-case-first with a real 5-row, revenue-ordered search sample above configuration, and verify keyword `sort` (e.g. `revenueDesc`) returns >0 ordered rows via fixture-backed coverage.

### 0.1 - 2026-11-12

- Add nullable `companyDescription` (public verksamhetsbeskrivning/business description) end-to-end: parsed and cleaned from company/detail pages when present (omitted when absent), included in enriched search/detail/monitor/new rows and `ENRICH_FIELDS`, exposed in dataset schema and README, with fixture-backed tests and no personal/contact data introduced.
- Strengthen foothold proof: README leads with use case and a real enriched output sample, keeps CEO/chairman person names separated from role titles, validates SNI/NACE on enriched rows, and confirms 20 enriched rows have >=80% public person names with no role-title-as-person or personal contact/birth data.
- Foothold proof verification: enriched rows keep person/title separation, valid SNI/NACE, and no personal/contact or birth data.
- Fix enriched person-name/title separation and NACE quality for battery search inputs: `ceo`/`ceoTitle` stay role titles while `ceoName`/`chairmanName` hold public person names (omitted when protected), no role-title-as-person or contact/birth data, and enriched rows keep valid NACE `sniCode`/`sniName` from company pages. Added fixture-backed enriched-quality coverage.
- Add structured `paymentRemarks` and `announcements` on detail, enriched search and monitor rows: parse payment-remark status and recent registry announcements/change-feed events from company pages, merge into enriched search results, include in monitor fingerprints, and expose in dataset views/README; omitted when absent.

### 0.1 - 2026-11-11

- Data-truth: separate `ceoTitle` and `ceoName` (and `chairmanName` when public) on detail, enriched search and monitor rows — title fields never contain person names and name fields never contain role titles; protected person data is omitted (no contact/birth identifiers). Enriched search and monitor fingerprints include the new fields.
- Correct SNI/NACE fields from page sources: prefer published NACE industry codes/names over internal category labels when available, and merge industry/SNI from company pages into enriched search rows.

### 0.1 - 2026-11-11

- Add `signatories` and `marketingProtection` fields on detail, enriched search and monitor rows (parsed from company pages), include them in search enrichment/monitor fingerprints, and omit them when absent.
- Add multi-year `accounts` history (up to 5 years: `fiscalYear`, `revenueKSEK`, `profitKSEK`, `equityRatio`, `employees`, `accountsScope`) on detail, enriched search and monitor rows while keeping latest flat financial fields backward-compatible.
- Add `output=diagnostic` preview mode: coverage/counts and up to 3 non-PII sample company rows (no phone/email/website) with `upgradeHint`; diagnostic runs do not charge PPE for company/change rows, while `output=full` behavior is unchanged.
- Diagnostic search/detail runs now push redacted preview company rows (no phone/email/website) so preview output contains data rows.
- No phone or email for sole traders (enskild näringsidkare: the person's own contact) and no mobile-number fallbacks; legal entities keep their switchboard phone and email.

### 0.1 - 2026-11-10

- Expose `address`, `boardTitles`, and `fTaxDescription` in the dataset overview view (table fields and labels) so the table shows key fields already returned by the Actor.

### 0.1 - 2026-11-10

- Add `default` values for `query` (`"volvo"`) and `sort` (`"relevance"`) in the input schema so agent-style `{}` runs are valid and self-describing.

- Accept a single `url` input field (company or search-result page) alongside `startUrls`, and add fixture-backed tests proving `sort=revenueDesc` returns revenue-ordered rows for `query=volvo`.

- 0.2 (2026-11-10): strip stray quote/whitespace wrappers from start/URL inputs so pasted /what/ URLs with sort params are rewritten and fetched as valid bransch-sök URLs instead of crashing with httpx InvalidURL.

- Fixture-backed regression test for the battery's pasted-URL input (battery #10, `/what/scania`, same shape as the failed run qb04lN5xcPbkSftfG): captured `search_bransch_scania_2026-11-10.gz` (25 rows) through the RESIDENTIAL proxy and asserted the rewritten `/bransch-sök?q=scania` fetch returns 10 real Scania rows.

- Site change fix: allabolag stopped accepting query strings on `/what/<term>` — `/what/volvo?sort=revenueDesc` now searches for the literal term `volvo?sort=revenueDesc` and returns 0 hits (the run that exposed it, qb04lN5xcPbkSftfG, first crashed on the Store form's `startUrls` objects). Keyword searches, `sort` and pagination now use `/bransch-sök?q=<term>&sort=...&page=...`, and pasted `/what/...` URLs are rewritten to that shape before fetching; page 2+ reads the paginated `companies` block instead of repeating the page-1 name matches.

- First-class `sort` input for keyword searches (`relevance`, `revenueDesc`, `revenueAsc`, `numEmployeesDesc`, `numEmployeesAsc`): the run appends `sort=` to `/what/<query>` so results arrive in the site's own server-side order (e.g. `revenueDesc` = biggest first) without hand-pasting a search URL. Default stays `relevance` (URLs unchanged), a pasted search URL keeps its own `sort`, invalid values fail fast with a clear message, and monitor state keys include the sort. README input table documents it.

- Split industry into flat `sniCode` + `sniName` (keeps `industry` for compatibility) and emit `latitude`/`longitude` plus `companyFormCode` when the source lists them. Coordinates come only from the source `location.coordinates` (EPSG:4326) and are omitted otherwise — nothing is invented. Search enrichment now also merges `companyFormCode` and coordinates from the company page; monitor fingerprints include the new fields. No personal contact fields are added. Dataset view and README document the new fields with real Volvo fixture rows.

- Captured live `bransch-sök` sorted pages for `volvo` and `konsult` through the residential proxy and added fixture-backed parser/main tests proving `sort=revenueDesc` returns revenue-ordered rows (battery failure cases ZP5ACsiUrPf1jtfen, w60PYxlMSJ40ZbXL9).

- Add corporate structure fields (`parentCompanyName`, `parentCompanyOrgNumber`, `parentCompanyCountryCode`, `numberOfSubsidiaries`, `numberOfCompaniesInGroup`) from company pages, merged into enriched search results and exposed in dataset overview/README.

### 0.1 - 2026-11-09

- Default `search` now enriches every result from its company page (`enrichSearch`, default on): equity ratio, F-tax/VAT/payroll-tax registration, share capital, legal form, status, registration date, CEO/board role titles, fiscal year and `fetchedAt` are merged into the search row. Best-effort — a blocked or missing detail page keeps the thin search row and the run still succeeds. No price change.
- Accept pasted allabolag search-result URLs (e.g. `https://www.allabolag.se/bransch-sök?q=volvo&county=Skåne`) in `startUrls`, `query` and `queries`: company URLs still go to detail, search URLs are fetched verbatim and paginated with `page=N` while keeping `q`, county/industry filters and sort server-side. Fixes the silent 0-row run on the documented paste-a-search-URL workflow. Parser now exposes `searchStore` query/sort meta and picks the block whose page matches the request.

### 0.1 - 2026-11-08

- New companies feed: set `newCompanies: true` to monitor allabolag's Nystartade bolag registry listing for newly registered Swedish companies, filtered by `county`/`municipality`/`industry` and diffed against the named state store so scheduled runs emit only unseen companies (`changeType: new`, `change` billing event). Adds `parse_new_companies` and a fixture-backed test; README documents the feed with a real row.
- Add optional `industry` text filter for search and the new companies feed.
- Label README output samples by mode and show the real default `search` output first (from `fixtures/search_what_volvo.html.gz`), so buyers see what a default run returns vs the fuller `detail`/`monitor` rows.
- Add lead/compliance/distress fields from `__NEXT_DATA__` company data (detail/monitor, and search when present): company `phone`/`email`/`website`, `fTaxRegistered`/`fTaxDescription`, `vatRegistered`, `payrollTaxRegistered`, `shareCapitalKSEK`, normalized `statusRemarks`, and derived `riskFlags` (bankruptcy/liquidation/merger/payment remarks). Monitor diffs these fields; dataset view and README updated with real fixture examples. Role titles and company contacts only (no personal contact data).
- Fix financial units and data quality: rename `revenueSEK`/`profitSEK` to `revenueKSEK`/`profitKSEK` (values are kSEK). Drop implausible `profitKSEK` when reported net profit exceeds net revenue (e.g. LM Ericsson). Always emit `fiscalYear`, `fetchedAt` and `accountsScope: legal_entity` with financial values so data vintage and scope are explicit.
- Clarify scope and completeness in the README: figures are legal-entity (Bolagsverket) accounts, not consolidated group results; a fields-by-mode table documents which fields `search` vs `detail`/`monitor` return; pricing states the all-in cost including Apify residential (SE) proxy billed separately.
- Drop the redundant `id` field (use `orgNumber`) and omit fields not present in the source rather than inventing them.
- First build: search allabolag.se by keyword, fetch by organisation number/URL, and monitor mode (new/changed/removed financials/status) with state in a named key-value store. Runs through Apify residential proxy (SE); per-input status rows and a run summary. Role titles only (no personal data).
