# Changelog of Remotive Jobs Scraper: Remote Job Listings from the Website (`mrbridge/remotive-jobs-scraper`) Actor

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

## Changelog

### 0.1.6 (2026-10-28)

- Cheaper saves. The progress is now saved every 20 job pages applied or every 60 seconds, whichever comes first, instead of after every job. It is still saved before the first request, at the end of the discovery, at the end of the run and when the platform asks (persist, migration, abort). The write after every job cost 44 % of a 1 000 job run in the 0.1.5 test run (about 0.05 USD out of 0.12 USD). Now it is about 0.003 USD.
- Still no duplicate after a restart. The jobs returned since the last save are read back from the dataset when the run starts again, as in 0.1.5, and skipped. The pages of the last batch that gave no job (expired, filtered, in error) are asked for again, at most 19.
- Removed `datasetRows`, the dataset count lags the writes, from `OUTPUT`, with the end-of-run warning about the dataset row count. The check reported a wrong gap and a warning for nothing. The check at the start of a restarted run is the only one and does not change. Input and rows are unchanged.

### 0.1.5 (2026-10-28)

- 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 the jobs returned since the last save were returned and billed a second time (1 001 rows for 1 000 jobs in a test run). 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 and after every offer applied, each save finished before the next offer is applied. This is one write to the key-value store per returned job, about 0.005 USD for 1 000 jobs. After a restart a job already returned is not asked for again.
- 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 job pages fetched again because an earlier execution had begun to apply them, also counted in `pagesFetched`.
- 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.4 (2026-10-27)

- Resume after a migration: a run that the platform aborts now stops returning jobs before it saves its state, as it already did on a migration. A job can no longer be returned after the save and be returned again, and billed again, after the restart.
- Input, dataset rows and the fields of `OUTPUT` are unchanged.

### 0.1.3 (2026-10-27)

- Resume after a migration: when the platform moves a run to another server, the run reads the sitemaps again and goes on with the offers it has not returned yet. A job already returned is not asked for again, not returned twice and not billed twice, `maxItems` counts the jobs of the whole run, and the `OUTPUT` counters add up over the whole run (the sitemap counters are those of the last reading).
- The key-value store holds a new internal record, `RUN_STATE`, with the job IDs already returned and the counters so far. It is for the run itself, its shape may change in any version.
- Default memory is now 512 MB (256 MB is still allowed).
- Input, dataset rows and the fields of `OUTPUT` are unchanged.

### 0.1.2 (2026-10-27)

- Source: the public site remotive.com (sitemaps, then one job page per offer) replaces the public job feed. See the README for the data source and the terms.
- Attempts: no new attempt after a 429 answer, one new attempt after a network error, a timeout, a truncated answer or a server error (5xx). The new attempt starts after the longer of `Retry-After` (or the short backoff) and the 1 second interval, counted from the start of the failed attempt. Every attempt is bounded at 45 seconds, body included.
- `OUTPUT` changes: the new fields `walksFailed` and `failedWalks` list the sitemaps that could not be fetched (20 at most), and the new `stoppedBy` value `fetchFailed` says that no sitemap could be read because a fetch failed. A job page that fails to load gives one row in the `errors` dataset and the run goes on. The `coverageNote` says how many planned sitemaps could not be read.
- Descriptions: e-mail addresses and phone numbers are still masked, links are kept. A link that carries an e-mail address is masked (its anchor is replaced by its text in `descriptionHtml`, the bare address becomes `[link removed]` in `descriptionText`), and `mailto:` and `tel:` anchors are replaced by their text. Tags and attributes of `descriptionHtml` are untouched.
- `location`: spaces are tidied, for example `Canada,  USA` becomes `Canada, USA`.
- `.actor/dataset_schema.json` declares the four fields of the site (`listingType`, `expiresAt`, `applicantCountries`, `companyWebsite`), and the attribution no longer repeats the 24 hour delay of the old feed.

### 0.1.0 (2026-10-26)

- First version, never published: Remotive public job feed, replaced in 0.1.2.
