# Changelog of Mobile.de Scraper — Germany Car Marketplace (`rastriq/mobile-de-scraper`) Actor

- **URL**: https://apify.com/rastriq/mobile-de-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/rastriq/mobile-de-scraper.md

## Changelog — Mobile.de Scraper — Germany Car Marketplace

### 2026-09-18 — build FTP-28: M1

- T6 (push 2026-09-18): input\_schema.json prefill/default outputSchema -> "ftp28" para modo live (fallback interno en main.py sigue en "english", pendiente de autorizacion futura).

### 0.4 — 2026-08-25 (tag `beta`)

Ruta de API (`_snapshot_method: "http"`) operativa y particionada. El defecto sigue en
`browser_v2` hasta cerrar los cuatro puntos abiertos.

**Añadido**

- Cabeceras `x-mobile-*` en el fetch a `/api/s/`. Sin ellas el endpoint sirve una versión
  antigua y desde el 24/08/2026 responde 400.
- Partición por dos ejes: año de construcción año a año, y marca para los que no publican año.
  Cobertura del 16,6% al **97,2%** en `ConstructionMachine`.
- `_FILTROS_VALIDOS` — lista blanca de los nueve filtros que la API respeta. Lo que no esté se
  descarta **con aviso**.
- `_snapshot_dataset_name` — dirige un run de prueba a un dataset desechable y no publica el
  puntero.
- `_probar_filtros` y `_analizar_filtros` — diagnóstico de bandas y de filtros soportados.
- Candado en la escritura al dataset. Elimina el 25% de duplicados que producía la carrera
  entre corrutinas.

**Corregido**

- `dom_item_to_ftp28` no emitía ningún campo canónico FTP-28.
- `marca` llegaba con el distintivo pegado (`"NUEVOKubota"`), corrompida en el 42,9%.
- `estado` invertido para todo anuncio nuevo: buscaba `"neu"` sobre `"NUEVO"`.
- `ubicacion` normalizada al formato del cliente.
- `Execution context was destroyed`: se elimina la navegación previa al fetch.
- `proxy_pool = ["apify_residential"] * 10` se usaba literalmente como URL de proxy.
- `numResultsFound` → `numResultsTotal`, con `raise` si no aparece.
- Sin `_dataset_id` el run aborta en vez de barrer hacia un sumidero.
- El fax deja de mapearse como teléfono.
- `vendedor_id` emite `None`, no `""`.

**Pendiente**

- 323 anuncios (2,8%) que ni el año ni la marca alcanzan.
- Verificar sobre una categoría grande (`VanUpTo7500`).
- `precio_neto` al 85,7% frente al 100% del DOM.
- `km`: la maquinaria no trae `ml`; la anomalía de agosto sigue sin explicarse.

Formato: que cambio, por que, y **la medicion que lo respalda**. Un cambio sin numero detras es
una opinion; en este repo no cuenta como entrada de changelog.

Las versiones son las de Apify (`mayor.menor`). La plataforma no admite numero de parche.

### \[0.3] — 21 de agosto de 2026

#### Anadido — resolucion del ID canonico (`src/id_utils.py`)

mobile.de usa dos sistemas de identificador para el mismo anuncio: uno publico de 9 digitos, visible
en la URL canonica (`/lkw-inserat/slug/323829529.html`), y uno interno de 14 que aparece en el
parametro `?id=` y en el endpoint `/api/s/`. El esquema FTP-28 espera el publico.

Las tres rutas de extraccion del actor producian formatos distintos:

| Ruta | Fichero | ID que obtiene |
|---|---|---|
| API REST `/api/s/` | `snapshot_http.py` | 14 digitos, interno |
| DOM del navegador | `main.py` + `browser_transport.py` | 14 digitos, interno |
| SSR HTML | `consumer_client.py` | 9 digitos, canonico |

`extract_canonical_id(ad_id, url, canonical_url)` recupera el ID publico a partir de la URL
canonica. Si el ID ya tiene 10 digitos o menos, lo devuelve intacto. La URL de navegacion sigue
usando el ID interno a proposito: el servidor de mobile.de lo necesita para resolver la ficha.

**Cobertura real, medida despues de desplegar.** El fix funciona **solo cuando el registro trae una
URL canonica**. En un run en vivo posterior al despliegue, 11 de 20 registros seguian saliendo con
14 digitos, porque la tarjeta del listado solo expone el enlace `?id=` y no hay ninguna URL
canonica que leer. Queda como **defecto abierto**, no como resuelto.

**El dato de agosto no se puede reparar desde el dataset.** De los 15.995 registros afectados
(14,6% de 109.362), el **100%** guarda unicamente la URL `?id=`. Recuperar su ID publico exige
volver a pedir cada ficha, con DataDome de por medio.

#### Pendiente

- Comprobar si `fetchDetails: true` resuelve el canonico en la ruta de listado. Si lo hace, el
  snapshot mensual puede activarlo y el defecto se cierra sin tocar codigo.
- `ext_debug_leaf_texts` es un campo de depuracion y se esta entregando al cliente en el output.
- El output duplica campos canonicos con otro nombre: `precio` junto a `valor`, `imagen_url` junto
  a `imagenes`. Dos nombres para el mismo dato acaban divergiendo.
- El puntero del registro declara `datasetId: 8ps3gu3yLBcVyGGud`, pero el nombre resuelve a
  `CAsBbtPNulwSo4COg`. El `datasetId` esta obsoleto.
