# Changelog of BuildZoom Scraper (`parsebird/buildzoom-scraper`) Actor

- **URL**: https://apify.com/parsebird/buildzoom-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/parsebird/buildzoom-scraper.md

## Changelog

### \[1.9] - 2026-07-08

#### Fixed

- Removed repeated phone numbers from listing results when BuildZoom exposes the same shared routing number across multiple contractor cards or pages.
- Scrubbed shared routing phone snippets from listing descriptions.
- Listing mode now verifies phone numbers from each contractor profile page instead of trusting listing-page phone snippets.
- Tightened detail-page phone extraction to use explicit telephone fields instead of arbitrary phone-like text on the page.

### \[1.8] - 2026-04-06

#### Changed

- Updated pricing: listing $0.004 ($4/1000), detail $0.007 ($7/1000)
- City field now clearly documented to include state abbreviation (e.g. `New York, NY`)
- Removed debug logging (HTML snippet dumps, KVS saves)
- Updated README with new pricing, city format guidance, and examples

### \[1.7] - 2026-04-06

#### Fixed

- PPE charge failures no longer stop the scraper. When pay-per-event is not configured, `Actor.charge()` returns a truthy value that was being misinterpreted as "limit hit", causing the scraper to stop after 1 result even though 25 were found. Charges are now fire-and-forget.

### \[1.6] - 2026-04-06

#### Fixed

- Fixed contractor name link regex: BuildZoom wraps names in `<a><div>NAME</div></a>` (with newlines), not plain `<a>NAME</a>`. Updated regex to handle `<div>` wrapper inside `<a>` tags. This was the root cause of only 1 contractor being extracted per page.
- Removed diagnostic debug logging from v1.5

### \[1.4] - 2026-04-06

#### Fixed

- Rewrote contractor extraction: now searches FORWARD from each priceRange for the name link, instead of searching the entire block. Fixes the issue where only 1 of 25 contractors was extracted because sidebar/navigation links polluted the block

#### Improved

- City input now accepts human-friendly formats like "New York, NY", "San Francisco, CA", "Chicago" — auto-converts to URL slug
- Updated input schema description and default city

### \[1.3] - 2026-04-06

#### Fixed

- Fixed HTML entity encoding: BuildZoom serves `&quot;` instead of literal `"` in priceRange markers — added `html.unescape()` before parsing
- Fixed address regex to handle addresses like "2250 2nd Ave" where the street name starts with a digit
- Fixed debug logging to count both `&quot;priceRange&quot;` and `"priceRange"` markers

### \[1.1] - 2026-04-06

#### Fixed

- Rewrote listing parser: BuildZoom pages use flat HTML without per-contractor wrapper divs. Now splits blocks by `"priceRange"` markers for reliable extraction
- Added address fallback for non-street-number addresses (e.g. "Cutler Bay, Miami, FL 33189")
- Added debug logging: HTML size, priceRange count, contractor link count per page
- Saves raw HTML to key-value store when no contractors found (for debugging on Apify)
- Added plumbing projects and sewer laterals to project breakdown parsing

### \[1.0] - 2026-04-06

#### Added

- Initial release
- Scrape contractor listings from BuildZoom by city and trade
- Filter by construction type (residential/commercial) and average project value
- Sort by BZ score, verified projects, client ratings, or project value
- Listing mode: name, BZ score, price range, address, phone, projects, rating, review count, project breakdowns
- Detail mode: license numbers/status/types, insurance amount/provider, bond amount/provider, verified license
- Pagination support (25 contractors per page)
- Pay-per-event pricing: `buildzoom-contractor-listing` ($0.002) and `buildzoom-contractor-detail` ($0.005)
- Deduplication by contractor slug
