# Changelog of Tcgplayer Scraper (`normdata/tcgplayer-scraper`) Actor

- **URL**: https://apify.com/normdata/tcgplayer-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/normdata/tcgplayer-scraper.md

## Changelog

### 2026-09-12 (5)

- Cleaned `custom_attributes` string values: TCGplayer's own API embeds real display markup
  directly in card text (`<strong>`, `<em>`, `<span style="...">`, `<br>` - confirmed live, not a
  one-off). `<br>` becomes a real line break; every other tag is dropped; the HTML entities
  actually seen decode to their real characters. Re-verified against 20 live results: 0 remaining
  HTML-looking values.
- Verified at 500 rows: 500/500 unique `product_id`, 0 duplicates, ~11s.

### 2026-09-12 (4)

- Fixed `listings`, `custom_attributes`, and `skus` (price-history mode) showing as raw text in
  the Apify Console's dataset table: they were declared with `"format": "json"`, which isn't a
  real Apify dataset-schema format value (confirmed against Apify's own docs) and silently fell
  back to plain-text rendering. Corrected to `"array"`/`"object"`. Also fixed the same mistake on
  `student-com-housing-scraper`'s dataset schema (`room_options`, `floorplans`, `images`,
  `reviews`), and added its missing `office_hours`/`accessibility`/`pet_policy`/`parking_info`
  fields to its dataset schema view while in there.
- Audited every field's real fill rate against 100 live results (product- and listing-level).
  `median_price` (27%) and `product_type` (0%) confirmed genuinely absent from TCGplayer's own
  response for most products, not a parsing gap - verified by diffing raw API responses directly.
- Confirmed `image_url` resolves to a real image (HTTP 200, `image/jpeg`) via direct header
  checks against several product IDs - not a broken or "proxied" placeholder.

### 2026-09-12 (3)

- Added `image_url`: TCGplayer's own search response has no product-image field at all, so this
  is built from `product_id` against TCGplayer's own image CDN and verified to return a real
  image for every product ID tested.

### 2026-09-12 (2)

- Tested at 1,000 and 3,000 rows (not just a small sample) and found two real issues:
  - Page fetches were sequential; switched to concurrent fetching (concurrency 8, verified as the
    safe ceiling - 15 caused a real timeout on the same query). 3,000 results dropped from ~92s to
    \~42-60s. A single page failing no longer crashes the run.
  - TCGplayer's own relevance search does not paginate against a stable view of the catalog - an
    unfiltered 3,000-row pull had 1,000+ duplicate `product_id`s before this was caught. Fixed
    with de-duplication that keeps fetching until it has enough genuinely new rows.

### 2026-09-12

- Initial release: `search`, `lookup`, and `priceHistory` modes over TCGplayer's own public
  search and price-history endpoints (no API key, no login, no anti-bot bypass needed - verified
  directly).
- One flat row per product: identity, game/set/rarity classification, market/median/lowest price,
  and every seller listing (condition, printing, language, seller name/rating/sales, verified and
  gold-seller flags, price plus shipping, quantity).
- `search` filters: name, game, set, rarity, listing condition, price range, foil-only, sort by
  market price (verified live), best-selling, or product name.
- `lookup` accepts direct TCGplayer product IDs; an unresolved ID comes back as an `error` row.
- `priceHistory` returns a daily price and sales-volume series per condition/printing/edition
  combination, for the `month` or `quarter` range - the only two TCGplayer's own endpoint
  supports (`day`, `week`, and `year` were tried directly and confirmed to return HTTP 400; not
  shipped as options).
- Verified at scale across 150 real, unfiltered results spanning 7 different TCGplayer games.
- Free-plan runs are locked to a fixed 10-row sample.
