# Changelog of Bing Videos Scraper (`searchapi/bing-videos-scraper`) Actor

- **URL**: https://apify.com/searchapi/bing-videos-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/searchapi/bing-videos-scraper.md

## Changelog

### \[3.0.1] - 2026-08-29

#### Added

- Fair multi-query search with `queries`, `maxItemsPerQuery`, per-query positions, and global interleaved positions.
- Source-backed platform, duration, view-count, short/live filters and relevance/view/date/duration sorting.
- Stable top-level `id`, explicit dataset provenance, extraction method, and requested filter context.
- Representative batch, filtered, URL, no-results, and invalid-input QA cases.

#### Changed

- Linked the external dataset schema from the Actor manifest and converted it to the current object/properties wrapper.
- Updated the runtime to Crawlee 3.18.1 and Playwright 1.62.1 with exact production versions.
- Buffered query results before one final fair dataset push while preserving the existing live Bing card extractor.

#### Fixed

- Removed three high-severity production dependency findings.
- Multi-query deduplication now uses query plus stable video identity so each search retains truthful context.

### \[2.0.1] - 2026-06-13

#### Fixed

- **Critical**: inlined Node-side helpers (`durationToSeconds`, `parseViewCount`, `normalizeDuration`, `platformFromUrl`, `toIsoDate`, `normalizeString`) inside the `page.evaluate` callback. The previous code called them by name, which works in Node but throws `ReferenceError` inside the browser context — and the per-card `try/catch` silently swallowed the error, so the actor was pushing zero records on every run.
- 0% → 100% record yield (55 unique cards → 50 records after the `maxItems` cap, single pass, ~4s runtime).

#### Verified

- End-to-end local run with `query="machine learning tutorial"`, `maxItems=50` produced **50/50 records** with zero failed requests.
- 100% fill rate on: `title`, `link`, `url`, `domain`, `platform`, `videoId`, `duration`, `durationSeconds`, `views`, `viewCount`, `channel`, `uploader`, `description`, `snippet`, `hostPageUrl`, `hostPageDomain`, `searchQuery`, `searchUrl`, `thumbnailHighQuality`, `thumbnailWidth`, `thumbnailHeight` (when present in DOM).
- 96% (48/50) on `publishedAt` — Bing returns relative time strings for the freshest items which the browser-side `toIsoDate` does not parse; the ISO date falls back to the displayed relative time in those cases.
- 32% (16/50) on `thumbnail` — Bing lazy-loads images on scroll, so cards rendered below the fold have no `src` set at extraction time.

### \[2.0.0] - 2026-06-12

#### Added

- New dataset fields: `type`, `resultType`, `searchQuery`, `searchUrl`, `country`, `language`, `scrapedAt`, `displayUrl`, `platform`, `channel`, `uploader`, `channelUrl`, `embedUrl`, `likeCount`, `dislikeCount`, `commentCount`, `publishedAtRaw`, `relativeTime`, `date`, `thumbnailHighQuality`, `thumbnailWidth`, `thumbnailHeight`, `tags`, `isLive`, `isShort`, `isAdult`, `isAd`, `favicon`, `additionalInfo`, `searchMetadata`
- `platform` — friendly platform name extracted from the video URL host (e.g. `YouTube`, `Vimeo`, `TikTok`)
- `thumbnailHighQuality` — high-quality thumbnail URL (from `data-src-hq`)
- `thumbnailWidth` / `thumbnailHeight` — thumbnail dimensions in pixels
- `isShort` — true if the video is a short (vertical) format
- `isLive` — true if the video is live
- `isAdult` — true if the thumbnail is marked as adult
- `isAd` — true if the result is a sponsored card
- `embedUrl` — direct embed URL (currently same as `link`, may diverge for embeddable players)
- `searchMetadata` object containing engine, market, country, language, page, query, resultType, scrapedAt
- New input fields: `mode` (`search` | `urls`), `startUrls`, `headless`, `market`
- New view "Full Details" showing every field
- New input mode `urls` to scrape arbitrary Bing Videos URLs via `startUrls`
- Uses shared `_canonical/normalize.js` (`normalizeVideoRecord`) for cross-actor consistency
- Smart channel-name extraction from `aria-label` (handles "uploaded by X" pattern)
- Smart description extraction from `aria-label` (handles "Click to play · desc" pattern)

#### Changed

- **Breaking** — `position` is now a global counter across pages (not per-page)
- `query` is kept as a backward-compat alias of `searchQuery`
- `url` is kept as a backward-compat alias of `link`
- `hostPageDomain` is kept as an alias of `domain`
- `source` is now also the channel name
- `channel` and `uploader` are now aliases of `source` for cross-actor compatibility
- Direct play URLs are now extracted from `.mc_vtvc_con_rc[ourl]` (the actual play URL) instead of `vrhm.murl` (which may be the embedded URL)

#### Fixed

- Better deduplication using the Bing `mid` (video ID) as the primary key
- Robust view-count parsing ("10M views", "1.2K views", "128 views")
- Robust duration parsing ("3:53:53", "0:26", "00:26")
- Skips "Shorts" / filter cards that don't have `.vrhdata` metadata

### \[1.0.0] - 2025-07-01

#### Added

- Initial release of the actor
- Full README documentation with usage examples and field descriptions
- Input schema with validation for all parameters
- Dataset output schema defining all output fields
- Structured source layout: `src/main.js`, `src/routes/handlers.js`, `src/routes.js`, `src/errors/`

#### Changed

- Dockerfile updated: all `COPY` commands use `--chown=myuser` to prevent EACCES build errors
- Removed `postinstall: npx crawlee install-playwright-browsers` (browsers pre-installed in base image)
- `playwright` kept in `dependencies` (not devDependencies) for correct runtime import resolution

#### Fixed

- Build reliability: resolved `EACCES: permission denied, open '/home/myuser/package-lock.json'` on Apify Cloud (exit code 243)
