# Changelog of Arbeitnow Jobs Scraper: Job Listings with Filters (`mrbridge/arbeitnow-jobs-scraper`) Actor

- **URL**: https://apify.com/mrbridge/arbeitnow-jobs-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/mrbridge/arbeitnow-jobs-scraper.md

## Changelog

### 0.1.8 (2026-10-28)

- Removed `datasetRows` from `OUTPUT` and the warning that went with it, the dataset count lags the writes. The count of the platform was behind the rows already pushed by 10 to 180 rows, so the field was wrong and the warning fired for nothing at the end of a normal run. The check of the dataset when a restarted run starts is unchanged: it is the one that prevents duplicates.
- Input and dataset rows are unchanged.

### 0.1.7 (2026-10-27)

- No duplicate after a restart without warning. A restart asked through the API, or a server failure, stops the run without telling it first, so the progress it had not saved yet was lost and a whole page of jobs could be returned and billed a second time (a recette run returned 1,806 rows for 1,470 jobs). Now the dataset is the reference: on a restart the run reads the jobs already in its dataset after the last saved point, and skips them. The billed count starts from the events the platform already billed.
- The progress is saved before the first request, after every page and at the end of the walk. After a restart at most the page being applied is read again (about 30 seconds), none when the run stopped between two pages.
- If the saved progress or the dataset cannot be read when a restarted run starts, the run fails with an error in the log and writes no `OUTPUT`, rather than risk returning or billing a job twice.
- `OUTPUT`: new field `datasetRows`, the number of rows in the dataset at the end of the run (read again once after 2 seconds when it differs from `jobsEmitted`, with a warning in the log if it still differs). New field `pagesRereadAfterResume`, the pages read again after a restart, also counted in `pagesRead`.
- If the run stops in the instant between saving a job and billing it, that job is delivered once and never billed.
- Input and dataset rows are unchanged.

### 0.1.6 (2026-10-27)

- Resume after a migration: when the platform moves a run to another server, the run goes on where it was. It restarts at the page it was applying, the pages already read are not asked for again (each page costs 30 seconds), and a job already returned is not returned twice and not billed twice. The first request after the move waits for the usual 30 second interval. `maxPages` counts the pages already read plus the ones that remain, `maxItems` counts the jobs of the whole run, and the `OUTPUT` counters (including `pageTimings`, 20 entries at most) cover the whole run.
- The feed changes every hour, so while a run is moved a listing can slide from a page not yet read to a page already read and be missed. A listing that shows up on two pages is returned once.
- An abort of the run by the platform now stops the returns before the state is saved, exactly like a migration, so a row is either returned and recorded or not returned at all.
- The key-value store holds a new internal record, `RUN_STATE`, with the job IDs already returned, the page being read and the counters so far. It is for the run itself, its shape may change in any version.

### 0.1.5 (2026-10-27)

- Deep pages are read. Arbeitnow serves its later pages (about 3 MB each) slowly, and page 5 of a run timed out at 40 seconds on both attempts. Each request is now bounded at 110 seconds, answer included (100 seconds for the request itself, 60 seconds to the first byte). The 30 second interval and the number of attempts are unchanged: a network error, a timeout, a truncated answer or a 5xx is retried once, a 429 never.
- The default memory is 512 MB (minimum 256 MB), because a page weighs about 3 MB of JSON.
- A run lasts about 30 seconds per page plus the emission of the jobs, longer when a page is slow.
- `OUTPUT` changes: the new field `pageTimings` lists, for each page fetched (20 at most), `page`, `attempts`, `ms` (from the start of the first request to the end of the answer) and `bytes`. The log has one line per page. The other fields keep their names and meaning.

### 0.1.4 (2026-10-27)

- Descriptions keep their links. Only e-mail addresses and phone numbers are masked, so a link to the application form or to the company site is no longer replaced by `[link removed]` and an HTML link keeps its `href`.
- A `mailto:` or `tel:` anchor, and a link that carries an e-mail address (written with `@` or encoded as `%40`), is replaced by its text in `descriptionHtml`. A bare link of that kind in a text becomes `[link removed]`. Phone numbers are not looked for inside a URL.
- `location` has its spaces normalized: trimmed, runs of spaces collapsed, one space after each comma (`Canada,  USA` becomes `Canada, USA`).
- Output changes: `descriptionText` and `descriptionHtml` keep their links, and `location` is tidier. No field is added or removed.

### 0.1.3 (2026-10-27)

- No change of behavior: the attempt limits are renamed `maxRateLimitedAttempts` and `maxNetworkAttempts`, and the README states when a retry starts and that a non-empty `errorsByKind` does not always mean a stop.

### 0.1.2 (2026-10-27)

- A run can no longer hang until the platform timeout. Each request is bounded at 45 seconds, answer included, and every timeout of the HTTP client is set. A run that reaches its internal time limit abandons the request in flight and stops with `stoppedBy` set to `deadline`.
- A network error, a timeout, a truncated answer or a server error (5xx) is retried once, 30 seconds after the failed request, so the 3 requests per minute of Arbeitnow are still kept. A 429 is still never retried.
- `OUTPUT` is written at the end of every run, including a run stopped by its time limit or by an unexpected error, followed by a final log line.
- `OUTPUT` changes: the new `stoppedBy` value `fetchFailed` says that a page could not be fetched after its retry (such a run used to say `null`), and the new fields `pagesPlanned` and `lastPageRead` show how far the run went. The `coverageNote` of such a run says after which page the walk ended.
- README: the input errors that the platform refuses before the run starts are no longer listed, and the cleaning of spaces in `title`, `company` and `location` is documented.

### 0.1.1 (2026-10-26)

- First usable version. The Actor reads the Arbeitnow job board feed and returns one row per job, newest first, with the canonical Arbeitnow URL on every row.
- Input: `searchTerms`, `locations`, `tags`, `jobTypes`, `postedWithinDays`, `remoteOnly` (default `false`, every listing is returned), `visaSponsorship` (default `false`, applied by Arbeitnow), `maxPages` (1 to 20, default 3), `maxItems` (default 100), `includeDescription` (default `true`). All filters except `visaSponsorship` are applied on the pages read.
- Output: job fields, description as text and HTML with e-mail addresses, phone numbers and links masked. Arbeitnow serves no salary and no logo, so those columns stay empty. Errors go to a separate `errors` dataset and are never billed.
- Billing: one `job` event per delivered job. No price is stated here, see the Pricing tab.
- The `OUTPUT` record summarizes the run (requests, pages read, listings read, filtered out, duplicates, jobs returned and billed, errors by kind, `stoppedBy`) and carries the Arbeitnow attribution.
- Limits: Arbeitnow allows 3 requests per minute, so requests are spaced by 30 seconds and never retried. The run ends when Arbeitnow announces no next page, on a 429 (`RATE_LIMITED`), on a 400 (`BAD_INPUT`, `stoppedBy` `badInput`), and cleanly after 3 blocked responses in a row.
- README: data source and terms, input and output tables, a sample row and a sample input checked by a test.

### 0.1.0 (2026-10-26)

- First version: Arbeitnow job board feed (`GET /api/job-board-api?page=N`), pages read in order, one request every 30 seconds, no retry.
- Input: `searchTerms`, `locations`, `tags`, `jobTypes`, `postedWithinDays`, `remoteOnly` (default false), `visaSponsorship` (default false, sent to Arbeitnow as visa_sponsorship=true), `maxPages` (1 to 20, default 3), `maxItems` (default 100), `includeDescription` (default true). The other filters are applied on the pages read.
- Output: one row per Arbeitnow job listing, billed with one `job` event. Errors go to a separate `errors` dataset and are never billed.
- The `OUTPUT` record summarizes the run (requests, pages read, listings read, filtered out, jobs returned and billed, errors by kind, `stoppedBy`) and carries the Arbeitnow attribution.
