# Changelog of Indeed Jobs Scraper — Salary, Rating, Full Description (`foxlabs/indeed-jobs-scraper`) Actor

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

## Changelog

### 0.1.10 — 2026-10-20 — README doğruluk düzeltmesi (kod değişmedi)

- AI-ajan bölümündeki istem hâlâ pivot ÖNCESİ mimariyi anlatıyordu: "`withDescription` ilan
  başına bir sayfa ekler" → doğrusu "arama başına bir toplu istek". 0.1.5'ten beri ilan sayfası
  hiç açılmıyor.
- Aynı bölümdeki ücret cümlesi yalnız ilan ücretini söylüyordu; arama ücreti ve açıklama ücreti
  eklendi. Fiyat tablosu, FAQ ve davranış 0.1.9'dan beri doğruydu — bu düzeltme yalnız README.

### 0.1.9 — 2026-10-20 — arama ücreti (`keyword-search` $0,005)

- Maliyet dilim başına SABİT (liste isteği + toplu açıklama isteği), gelir ilan başına.
  Ölçüm: Unblocker $0,0013/istek; açıklama kapalı + `maxItems=1` koşusunda maliyet ~$0,0016,
  bize kalan $0,00164 → marj ~%2. Yeni olayla aynı koşuda bize kalan $0,0056 → marj ~%72.
- Ücret yalnız **en az bir ilan teslim eden** sorgu dilimi için. Bloklanan, yüklenemeyen,
  kart vermeyen ya da tamamı filtrelenen dilim ücretsiz — mağaza kartındaki
  "Empty results ... are never charged" vaadi bozulmadı.
- 45 ilanlık dolu dilimde ücret toplam faturanın **%1,8**'i. İlan ($0,002), açıklama ($0,004)
  ve başlatma ($0,00005) fiyatları DEĞİŞMEDİ.
- Fiyat kaydı 18:43'te gönderildi, **18:58 UTC'de başlıyor** (ikinci kayıt; ilki 17:36).
  Koşu raporunda ve Standby yanıtında `searches` alanı.

### 0.1.7 — 2026-10-20 — Standby parametre kusuru

- `/jobs?location=Dallas, TX` çağrısı konumu virgülden bölüp **iki dilim** açıyordu
  (yerel Standby sınamasında yakalandı). Parametreler artık dizi olarak okunuyor;
  birden çok değer için parametre tekrarlanır (`?query=rn&query=lpn`). Regresyon testi eklendi.

### 0.1.6 — 2026-10-20 — platformda doğrulandı, 512 MB, fiyat girildi

- Platform koşuları: `T0CeerUsuB64P6QLR` (1024 MB, 44 sn) ve `n8EUmNhT65bal4ZI2`
  (512 MB, **6 sn**) → ikisinde de 47 kart okundu, 15 ilan teslim, **15/15 açıklama**
  tek istekte, medyan 3.750 karakter. Tepe bellek 58 MB → varsayılan bellek 512 MB.
- Ölçülen maliyet: Unblocker 20 birim = $0,003 (dilim başına 2 istek) + compute $0,0002.
  45 ilanlık dolu dilimde ilan başına ~$0,00007.
- Fiyat kaydı gönderildi: `job` $0,002 · `job-description` $0,004 ·
  `apify-actor-start` $0,00005 (başlangıç 17:36 UTC). README fiyat tablosu güncellendi.

### 0.1.5 — 2026-10-20 — MİMARİ PİVOT: tarayıcı yok, düz HTTP + Unblocker

Kanıt (hepsi gerçek istek, ayrıntı `_QA.md`): konut çıkışı + headful Chromium platformda
Cloudflare Turnstile'a takılıyor (403 "Just a moment...", bir koşuda 5 oturumda da geçemedi),
ilan sayfası her yoldan 401 "Sign In". Unblocker + düz HTTP ise liste 200 (47 kart) ve
**/rpc/jobdescs tek istekte 47/47 açıklama** veriyor.

- Playwright, Xvfb, headful koşma, konut oturum döndürme, `detailDelayMs` **kaldırıldı**.
  Taban imaj `apify/actor-node:20`; dilim başına **2 istek** (liste + toplu açıklama).
- Birim maliyet: açıklamalı ilan $0,0011 → **$0,000058** (19 kat düşüş); marj %99.
- `employmentType` doğru kaynağa bağlandı: kartın `jobTypes` alanı %6 doluydu,
  `taxonomyAttributes.job-types` **%83**.
- **Yeni kolonlar:** `benefits` (401(k), diş/göz sigortası, eğitim desteği — %67 dolu) ve
  `schedule`. Rakiplerde yan hak listesi yok.
- `validThrough` **kaldırıldı**: tek kaynağı giriş duvarının arkasındaki ilan sayfası.
  Boş kolon ship edilmez; README neden kaldırıldığını söylüyor.
- `salaryCurrency` maaş rakamı yoksa artık `null` (15 satırın 5'inde anlamsız "USD" yazıyordu).
- Açıklama metninde satır başı sonrası boşluklar temizlendi.
- Testler 17/17.

### 0.1.4 — 2026-10-20 — açıklama artık TOPLU uçtan; giriş duvarı aşıldı

- **Platform duvarı (ölçüm kpfsATUxUwjQEfsfm):** kanonik `/viewjob?jk=` sayfası konteynerde
  **HTTP 401 "Sign In | Indeed Accounts"** veriyor (yerelde 12/12 açılıyordu) → açıklama 0/3.
- Çözüm: açıklamalar liste sayfasının oturumundan Indeed'in kendi toplu ucuyla alınıyor —
  `GET /rpc/jobdescs?jks=<20 anahtar>`. İlan başına sayfa açılmıyor: giriş duvarı aşılır,
  koşu hızlanır, bant genişliği (dolayısıyla maliyet) düşer.
- Yedek yol: gömülü ilan sayfası (`&viewtype=embedded`) + görünür gövde (`#jobDescriptionText`).
- Log her dilimde açıklamanın hangi yoldan geldiğini söylüyor (toplu uç / sayfa, rpc HTTP durumu).

### 0.1.3 — 2026-10-20 — detay sayfasında da blok yönetimi + tanı

- Platform ölçümü (jh1dtCugHM0OF076h): liste 3 oturum döndükten sonra **47 kart** verdi,
  ama **açıklama 0/3** geldi. Detay sayfası da Cloudflare ekranına düşüyor; artık orada da
  oturum döndürülüp yeniden deneniyor.
- Açıklama çıkmayan her ilan için HTTP durumu, sayfa başlığı ve bulunan JSON-LD blok sayısı
  log'a yazılıyor; ilk örnek `no-description-detail.html` anahtarına kaydediliyor.

### 0.1.2 — 2026-10-20 — Cloudflare: UA dayatması kaldırıldı, challenge beklenir, oturum döner

- **Kök neden (ölçüm, platform koşusu 9a3C8cu0wlvLIAQ0U):** konteynerde `HTTP 403
  "Just a moment..."` + Turnstile. Kod Linux konteynerde **Windows Chrome UA'sı** dayatıyordu;
  UA artık zorlanmıyor, tarayıcının kendi kimliği kullanılıyor.
- Cloudflare ekranı gelirse 30 sn'ye kadar kendi kendine çözülmesi beklenir.
- Dilim bloklu görünürse konut oturumu değiştirilip yeniden denenir (en çok 4 tur).
- `looksBlocked` artık Turnstile/challenge imzasını da tanıyor — bloklu sayfa "sonuç yok"
  diye sunulamaz.

### 0.1.1 — 2026-10-20 — kart vermeyen dilimin tanısı

- Sayfa açıldığı hâlde hiç kart çıkmazsa artık sessiz geçmiyor: HTTP durumu, sayfa başlığı ve
  bayt sayısı log'a yazılıyor, sayfanın kendisi `zero-cards-slice-N.html` anahtarıyla koşunun
  key-value store'una kaydediliyor. İlk platform koşusu (0.1.1, 16:50) tam bu durumu verdi —
  `slicesRead 1`, `kart 0`, blok imzası yok — ve tanı olmadan nedeni söylenemedi.

### 0.1 — 2026-10-20 — ilk sürüm

- **Indeed iş ilanları**: yapılandırılmış maaş (`salaryMin`/`salaryMax`/`salaryPeriod`/`salaryCurrency`),
  işveren puanı ve yorum sayısı, Indeed'in kendi etiketleri, tam açıklama, `postedAt`/`createdAt`/
  `validThrough` ISO tarihleri, kanonik ilan bağlantısı. 23 ülke sitesi.
- **Mimari: sorgu dilimleme, sayfalama değil.** Indeed derin sayfalamayı giriş duvarının arkasına
  koydu (ölçüm: gerçek tarayıcıda `&start=10` → "Sign In | Indeed Accounts"). Kapsama anahtar
  kelime × konum çiftleriyle büyür, çift başına ~45 ilan. README bunu açıkça söylüyor.
- **Erişim yolu:** konut çıkışı + gerçek tarayıcı, HEADFUL. Ölçümler (2026-10-20): düz HTTP 403 ·
  veri merkezi IP'si 403 "Security Check" · Unblocker listeyi açıyor ama detayda 502 ·
  headless'ta detay JSON-LD vermiyor (0/4) · headful + konut 5/6, ev IP'sinde 4/4.
- **Tempo bir kalite ayarı:** detaylar arasında 5 sn → 5/6 açıklama; hızlı gidince 1/5.
  `detailDelayMs` varsayılanı 5.000 ms.
- **Fiyat:** `job` $0,002 · `job-description` $0,004 — açıklama gerçekten dönmediyse ücret YOK.
  Bloklu sayfa, ağ hatası, yayından kalkmış/sahte ilan, filtrelenen satır ve boş sonuç ücretsiz.
- **Kaynağa ulaşılamazsa koşu BAŞARISIZ biter** ("sonuç yok" diye sunulmaz); Standby yolunda
  aynı durum HTTP 502 döner.
- Testler: 19/19 (gerçek arama sayfası fixture'ı + nöbetçi değer regresyonları).

#### Yayın öncesi yerelde bulunup düzeltilen kusurlar

- Indeed tek uçlu maaşta eksik ucu `-1` ile veriyor → satıra negatif maaş yazılıyordu, artık `null`.
- Kartın `viewJobLink`i `viewtype=embedded` taşıyor, o sayfada JSON-LD yok → açıklama 0/4 geliyordu;
  URL artık ilan anahtarından kanonik kuruluyor (12/12, 10/10 açıklama).
- Puansız işverene `companyRating: 0` geliyor → "0 yıldız" gibi okunuyordu, artık `null`
  (yorum sayısı da öyle); `salaryCurrency: ""` → `null`.
- JSON-LD'de çift kaçışlı varlık (`&amp;amp;`) tek geçişte çözülmüyordu → döngüyle çözülüyor.
- Liste DOM'u her koşuda farklı bir sahte `data-jk` taşıyor (detayı "Not Found") → tek doğru kaynak
  gömülü mosaic JSON; sahte/kapanmış ilan teslim edilmez ve ücretlenmez.
- Sayfa hiç yüklenemediğinde "eşleşen ilan yok" deniyordu → taşıma hatası artık ayrı sayılıyor.
