# Changelog of ParuVendu Scraper 🇫🇷 Immobilier Particulier + Agence (`tagadanar/french-real-estate-paruvendu`) Actor

- **URL**: https://apify.com/tagadanar/french-real-estate-paruvendu/changelog.md
- **Full Actor documentation**: https://apify.com/tagadanar/french-real-estate-paruvendu.md

## Changelog

### 2026-09-30

- **Fixed: prices were 10–100x too high on most listings.** The small photo
  counter on each card ("4" photos) was read as the first digits of the price,
  so a 455 000 € flat came out as 4 455 000 €. Prices are now read from the
  price field itself; €/m² and the `minPrice` / `maxPrice` filters were
  affected too and are correct again.
- Fixed: city was empty on the commune pages ParuVendu now serves
  (`/immobilier/vente/appartement/clichy-92110/`); it is read from the card
  heading.
- A commune search with no ads is redirected by ParuVendu to the whole
  département listing. The run now stops there and says so instead of
  scraping (and charging for) ads you did not ask for.
- "No listings matched" is only said when ParuVendu's own results count is 0;
  empty pages without that proof are reported as a possible layout change.
- A search URL pasted without its trailing slash (which ParuVendu answers
  with a 404) is corrected automatically.
- A search URL that does not exist on ParuVendu (a mistyped or invented
  city/commune in the path — ParuVendu answers it with "Erreur 404") is now
  reported as exactly that: "ParuVendu has no search page at <url> (HTTP 404)
  — build the search on paruvendu.fr and paste its URL." It used to be
  reported as a possible page-layout change. A 404 on a later page of a real
  search is still just the end of the results.

### 2026-08-29

- README: the five filter inputs (`minPrice`, `maxPrice`, `minSurface`,
  `minRooms`, `propertyTypes`) are now documented alongside `keywords`. They
  were all in the input form, but the page only said "filters for price,
  surface, rooms, property type and keywords" without naming any of them.

### 2026-08-29

- Fixed: a short run timeout (180 s or less) reserved the whole budget for
  the finishing phase, so the run stopped immediately and returned nothing.
  Scraping now always keeps at least half of whatever time the run has.
- The run now watches its own clock. A deep search used to be killed by the
  platform timeout mid-page, losing every listing that had not been pushed yet
  — worst with detail scraping on, where a listing only ships once its ad page
  comes back. The actor now stops taking on new pages while there is still time
  to finish and push what it has, and ends **successfully** with "Stopped at
  the run time limit: N rows delivered, raise the run timeout or lower
  maxResults."
- Page fetches are bounded by the time actually left: past the deadline a
  queued page is dropped without being fetched at all, and its retry ladder is
  cancelled rather than rotating proxy sessions into the timeout.
- **New input: Max result pages per search URL** (`maxPagesPerUrl`, default 20).
  It was always there in the code — the single biggest control over how long a
  run takes — but you could not see or set it.
- Honest limits in the input form: **Max listings** now tops out at 4,000
  instead of advertising 10,000 that no run could reach, **Search URLs**
  accepts up to 20 per run, and **Keywords** up to 50.
- Every run now ends with a status message. A run that was challenged by
  ParuVendu, cut short by the clock, or emptied by your own filters says which
  — instead of reporting "no listings matched".

### 2026-07-13

- README: pricing table now discloses the $0.001 actor-start fee, which the 07-12 floor raise added but the copy never mentioned.

### 2026-07-12

- Invalid input no longer fails the run. The run now finishes cleanly with a clear explanation in its status message, so a typo or an empty list is easy to spot and fix.
- List inputs now accept datasets piped straight from another scraper: entries
  that are objects are read through their usual key names (url/link,
  query/keyword/title, name/company and similar) instead of being rejected.

### 2026-07-11

- Billing: on paid runs every row is billed before it is written, and a run
  now stops visibly if billing fails instead of continuing unbilled.

### 2026-07-09

- Input is now tolerant of common shapes that previously failed the run: a bare
  string / bare object / delimited string for searchUrls is coerced into a list
  instead of erroring. Empty input still errors.

### 2026-07-06

- Première version publique sur l'Apify Store.
- Annonces immobilières ParuVendu.fr (vente et location) : prix, €/m², surface, pièces, ville, photos, DPE.
- Filtre « particuliers uniquement » pour la pige immobilière.
- Toutes les pages d'une recherche suivies automatiquement.
