A tool for finding and ranking used cars from Blocket.se. It scrapes car listings, enriches each one with vehicle history data from Biluppgifter.se, and presents them in a scored, filterable web UI.
- Scraper — given a Blocket search URL, paginates through all results and fetches each listing's details.
- Enrichment — for every car, looks up its registration number on Biluppgifter to get mileage history, market valuation, inspection dates, ownership count, and warning flags.
- Scoring — the web UI ranks cars using configurable rules (linear interpolation and boolean flags). Rules and weights are editable in the browser and persisted to localStorage.
Prerequisites: Node.js 18+, an Apify account with API access.
# Install backend dependencies
npm install
# Install frontend dependencies
cd web && npm install && cd ..Copy .env.example to .env and fill in your Apify token:
cp .env.example .envnpm run find-cars "https://www.blocket.se/mobility/search/..."Paste any Blocket car search URL. Results are written to generated/carsData.json.
Note: The scraper caches HTML responses in
cache/to avoid redundant network requests on reruns.
cd web && npm run devOpens at http://localhost:5173. The UI reads generated/carsData.json via the Vite dev server and renders each car ranked by score. Use the sliders icon to open the rules editor.
├── src/
│ ├── index.ts # CLI entry point
│ ├── getAllCars.ts # Car enrichment and data persistence
│ ├── blocketScraper.ts # Blocket pagination and list scraping
│ ├── types.ts # CarData interface
│ ├── bilupgifter/
│ │ ├── getBilupgifterData.ts # Biluppgifter scraping and parsing
│ │ ├── getMileageConsistency.ts # Linear regression on mileage history
│ │ └── models.ts # Biluppgifter types
│ └── util/
│ ├── apifyFetch.ts # Apify-backed fetcher (for bot-protected pages)
│ ├── smartFetch.ts # Rate-limited fetcher with file cache
│ ├── cache.ts # Cache key/path utilities
│ └── general.ts # JSON parse helper
├── web/
│ └── src/
│ ├── App.tsx # Main layout and data loading
│ ├── CarCard.tsx # Car tile component
│ ├── RulesModal.tsx # Scoring rules editor
│ ├── scoring.ts # Scoring engine
│ ├── rules.ts # Default scoring rules
│ └── types.ts # Car interface for the UI
├── models.ts # Zod schemas for Blocket API responses
├── generated/ # Output data (gitignored)
└── cache/ # HTTP response cache (gitignored)
Rules are defined in web/src/rules.ts and editable at runtime via the UI.
- Linear rules — map a numeric field to a score via two control points (e.g., 0 km → 30 pts, 230 000 km → 0 pts).
- Flag rules — add or subtract a fixed score when a condition is met (e.g., meter tampering warning → −30 pts).
All rule changes are saved to localStorage and merged with any newly added default rules on next load.