# Changelog of LinkedIn Company Scraper – Employees, Followers & Firmographics (`foxlabs/linkedin-company-scraper`) Actor

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

## Changelog

### 0.2.22 — 2026-10-02 — lookup fee narrowed before it starts: HTTP 999 stays free

- The lookup fee announced in 0.2.21 (from 17 October 2026) will **not** apply to a handle LinkedIn refuses with HTTP 999 — that answer can also mean LinkedIn is blocking us, and failures on our side are free. Charged: delivered companies and handles that certainly lead nowhere (HTTP 404/410) or to another organisation's page.

### 0.2.21 — 2026-10-02 — lookup fee announced for 17 October 2026

- **Pricing change from 17 October 2026 (15:00 UTC):** every company looked up costs a $0.0005 `company-lookup`, and a delivered row drops from $0.004 to $0.0035 — a delivered company costs $0.004 as before. A company looked up but not delivered because of the input (HTTP 404, another organisation's page, a refused handle) costs only the $0.0005 lookup. Lines never looked up, inputs not reached before the timeout and failures on our side stay free. The code is live now and charges nothing extra until the new price takes effect (`src/billing.js`).

### 0.2.20 — 2026-10-02 — clear reasons instead of failed runs; names checked; no crash on one bad line

- **A run that delivers nothing because of the input now ends SUCCEEDED** (since 0.2.19 it ended FAILED), with a status message that names the reasons and every line in `FAILED_LOOKUPS`; nothing is charged per company. It ends FAILED only when nothing was delivered and LinkedIn could not be reached or read (network errors, HTTP 429/5xx, HTTP 999 on several handles, a page that loaded without company data).
- **Names are checked.** A company name is still turned into LinkedIn's usual handle, but the row is kept only if the page's name matches the name you typed; otherwise the line goes to `FAILED_LOOKUPS` ("belongs to a different organisation") and is not charged. Before this fix "Arçelik" returned a 1-employee page called "karbank" and was charged. Turkish ı and ß, ø, ł, æ are now transliterated (`Yapı Kredi` is guessed as `yapi-kredi`, no longer `yap-kredi`).
- **New output field `matchedBy`** on every row: `url`, `handle` or `name-guess`.
- **Lines that cannot work are reported, not looked up or silently dropped**: numeric company IDs, Sales Navigator links, person / school / showcase pages, website URLs, empty lines and lines without Latin letters — each is listed in `FAILED_LOOKUPS` with the reason, without a request. Empty and non-Latin lines used to vanish without a trace. A line with several comma-separated companies is now split (a legal form such as ", Inc." is not split off).
- **One broken URL no longer fails the whole run.** A malformed %-sequence used to stop every run it appeared in with "URI malformed", even when the other companies were fine.
- **Dead lines fail fast.** A page that does not exist (HTTP 404) is no longer retried (it was retried 5 times, 2–29 s per line); HTTP 999 is tried at most twice. Ownership lookups give up after 15 s.
- **Nothing is lost at the timeout.** `FAILED_LOOKUPS` is saved at least every 10 s while the run goes on and always before it ends, and about 45 s before the run timeout the actor stops on its own, keeps what it delivered and lists the companies it did not reach in the new `UNPROCESSED` record.
- **`{ "url": "…" }` entries are read.** Request-list objects sent through the API are taken as their URL instead of being rejected.
- **`FAILED_LOOKUPS` entries changed:** `input` is now the line exactly as you gave it (it was the handle); the handle that was tried is in `handle`; new fields `cause` (`input` or `actor`) and `httpStatus`.
- README: removed "relevance-ranked name search or exact registry-ID lookup" and the registry-style profile claims (status, legal form, formation date) — the actor never did either; added run-time guidance for big lists. `scrapedAt` corrected to `scrapedAtIso`.
- Internal: input handling moved to `src/input.js` with offline unit tests (`npm test`).

### 0.2.19 — 2026-09-29 — failed lookups are no longer charged; names work

- **Billing fix.** A lookup that could not be read (for example a handle with no public page) was written to the dataset as an error row — and, because pricing is per dataset row, charged like a company. That contradicted the README, which since 0.2.18 said failed lookups are never charged. They now go only to the run log and the `FAILED_LOOKUPS` record in the key-value store, and are not charged. Price per delivered company is unchanged.
- **Company names are accepted.** A line like `Goldman Sachs` used to be rejected, and a list made only of names failed the whole run with "No valid companies". A name is now turned into LinkedIn's usual handle (`goldman-sachs`); if that page does not exist, the lookup is listed in `FAILED_LOOKUPS`.
- **A run that delivers nothing ends as failed**, with the reasons in its status message, instead of succeeding with only error rows.

### 0.2.18 — 2026-09-20 — README corrected against the real input schema

- **Every code example was broken.** The AI-agent, cURL, JavaScript and Python examples used keys that do not exist in this Actor's input schema (`queries`, `maxResultsPerQuery`) with a literal placeholder string instead of a real value, and the input table listed those phantom fields instead of the real ones. Anyone who copied an example got a failing run. All examples now match the schema prefill exactly.
- **Removed promises the Actor does not keep:** "formation / status monitoring", "a canonical registry record for KYB and due diligence", and "every row carries `query`" (there is no `query` field). Fixed a duplicated word in the intro.
- **Billing wording corrected.** The README said "empty/failed lookups are never billed" without saying why. Failed lookups are not written to the dataset at all — they are reported in the run log and in the `FAILED_LOOKUPS` record in the key-value store — so there is no row to charge. Stated plainly instead of implied.
- No code, output field or pricing change.

### 0.2 — 2026-09-07

- **Enabled AI-agent payments (x402) + rebuilt the README to the full standard** (What-is / when, AI-agents + x402 agentic payments + MCP, Overview, Features, Use cases, Integration, FAQ, Troubleshooting, Support & contact).

### 0.0

- Initial release: data from public LinkedIn company pages by name or registry ID.
