L logiover
business · Jul 9, 2026 · 7 min read

How to Scrape DBA.dk Denmark Classifieds & Prices in 2026

Extract dba.dk listings at scale — prices in DKK, seller type, location, and full car specs. How Denmark's biggest marketplace exposes its data.

DBA.dk (Den Blå Avis) is Denmark’s largest second-hand marketplace — the place Danes go to sell cars, electronics, furniture and everything in between. If you want that data for price modeling or lead generation, you’ll quickly notice there’s no public developer API, and the pages render most of their content client-side. This guide covers what dba.dk actually exposes, how to read it without a browser, and where the practical limits are when you pull it at scale.

What’s worth extracting

Every dba.dk listing carries a consistent set of fields once you read the site’s own structured payload. This scraper returns one clean row per listing, roughly 25+ fields:

  • IdentitylistingId (dba.dk’s unique ad ID and your only stable join key), url (canonical listing URL), and title.
  • Pricingprice as a clean number in DKK, plus priceRaw (the original 24.500 kr. text) and currency (DKK).
  • Locationlocation (city/town) and approximate latitude / longitude.
  • SellersellerType tagged private or dealer on every row, plus tradeType (e.g. Til salg for sale, Gives væk for free).
  • FreshnesspostedDate in ISO 8601 so you can sort and filter by how new a listing is.
  • Categorizationcategory (top-level: vehicles or general), subCategory (the dba.dk search/category title like Personbil or Elektronik og hvidevarer), and brand for general goods.
  • Mediaimage (main image URL) and imagesCount.

For vehicle listings (category = vehicles), each row adds the specs that make Danish used-car analysis possible: make, model, year (registration year), mileage (in km), fuel, transmission, and regNo (the Danish number plate, when the seller listed it).

Two provenance fields round out the record: sourceUrl (which search/category URL the row came from) and scrapedAt (the scrape timestamp).

How dba.dk actually serves its data

DBA.dk runs on two platforms behind one domain, and the scraper handles both transparently:

  • The cars search (/biler/biler/) redirects to a mobility URL.
  • A keyword search or homepage category link redirects to a recommerce URL (recommerce/forsale/search).

You don’t need to reason about which is which — you paste the URL straight from your browser’s address bar after setting your filters, and the parser covers both. The two live URL shapes look like this:

https://www.dba.dk/mobility/search/car?registration_class=1
https://www.dba.dk/recommerce/forsale/search?q=iphone

Rather than parsing the rendered DOM (which is brittle and changes often), the scraper reads dba.dk’s own embedded listing JSON payload — the same structured data the front-end uses to draw the page. That’s why the fields come back typed and consistent instead of scraped from HTML text. It’s effectively an unofficial dba.dk API: no login, no cookies, no key.

A minimal run is just a URL and a cap:

{
  "searchUrls": ["https://www.dba.dk/mobility/search/car?registration_class=1"],
  "maxResults": 1000
}

You can mix vehicle and general-goods URLs in a single run by adding more entries to searchUrls. Leave searchUrls empty and it defaults to scraping Denmark used cars.

Run the DBA.dk Scraper on Apify — paste any dba.dk search or category URL and get structured DKK-priced listings with seller type and car specs. No login, no API key. Export to JSON, CSV or Excel.

The access reality

DBA.dk is far friendlier than the heavily-defended marketplaces. Two things matter in practice:

  • No Cloudflare challenge. dba.dk is not sitting behind an anti-bot wall, so datacenter proxy is enough — runs stay fast and cheap. You only switch to residential in proxyConfiguration if you ever start seeing blocks, which is rare.
  • A hard per-search cap. This is the real ceiling, and it’s a site limit, not a scraper limit: dba.dk caps any single search or category at 50 pages (~2,600 listings). If your query would return more, you won’t get past that wall no matter what tool you use.

The way around the cap is query splitting. Instead of one broad search, break it into narrower slices — by category, brand, price band, or region — and paste each URL into searchUrls. Ten narrow searches of 2,600 each get you far more coverage than one broad search that dies at 2,600. Auto-pagination and de-duplication by listingId handle the rest, so overlapping slices won’t double-count.

One scope note worth knowing up front: the scraper reads the search payload, not individual detail pages. That keeps runs fast and cheap, but it means free-text descriptions, full equipment lists, and VINs are out of scope. You get everything in the listing card — make, model, year, mileage, fuel, transmission, plate, price, location, image — but not the long-form body of each ad.

Example output

A trimmed used-car row (vehicle fields included):

{
  "listingId": "22052485",
  "url": "https://www.dba.dk/mobility/item/22052485",
  "title": "Volvo S40",
  "price": "24500",
  "priceRaw": "24.500 kr.",
  "currency": "DKK",
  "location": "Kruså",
  "latitude": "54.86647",
  "longitude": "9.43728",
  "category": "vehicles",
  "subCategory": "Personbil",
  "sellerType": "private",
  "postedDate": "2026-06-07T17:04:58.000Z",
  "make": "Volvo",
  "model": "S40",
  "year": "2006",
  "mileage": "252000",
  "fuel": "Benzin",
  "transmission": "Manuelt",
  "regNo": "EF86096"
}

A general-goods row (electronics) drops the vehicle block and adds brand and tradeType instead:

{
  "listingId": "22052953",
  "title": "Apple MacBook bærbar computer 13\" grå",
  "price": "2000",
  "currency": "DKK",
  "location": "Vejle",
  "category": "general",
  "subCategory": "Elektronik og hvidevarer",
  "sellerType": "private",
  "tradeType": "Til salg",
  "brand": "Apple",
  "imagesCount": "10"
}

Typical use cases

  • Denmark used-car price analysis — track DKK prices, mileage and year by make/model to build depreciation curves, valuation models, and market comps from real Danish used-car data.
  • Marketplace & competitor monitoring — watch prices, inventory, and new-listing velocity across categories on Denmark’s biggest classifieds site; schedule daily pulls and diff on listingId to catch new listings and price drops.
  • Dealer lead generation — set sellerType to dealer to build a clean list of Danish car dealers and active sellers by region or category.
  • Resale & arbitrage research — spot underpriced electronics, furniture, and gear for flipping between dba.dk and other platforms.
  • AI / ML datasets — feed Danish-language product titles, prices, and attributes into pricing models and training sets.
  • Price tracking & dashboards — monitor demand trends and price movement across the Danish second-hand market over time.

The common thread: value comes from freshness and breadth. A one-off snapshot is a curiosity; a daily-refreshed feed across dozens of narrow searches is a real dataset you can model against.

Build-it-yourself vs. managed

You can build this yourself — dba.dk isn’t behind an anti-bot wall, so a determined engineer can reverse the embedded payload, handle the mobility/recommerce redirect split, wire up pagination with dedup, and normalize the DKK price text. That’s a couple of days of work plus ongoing maintenance every time dba.dk tweaks its payload shape or its two platforms diverge.

The managed actor runs on pay-per-result pricing: you pay for the listings you actually collect, not for compute time or idle servers. Because datacenter proxy is enough, per-row cost stays in the fraction-of-a-cent range. For a typical setup — a dozen narrow searches refreshed daily — you’re looking at low single-digit dollars a month, with the redirect handling, dedup, and price parsing already solved and kept green.

Common pitfalls

A few things specific to dba.dk that will bite you if you’re not expecting them:

  • The 50-page cap is non-negotiable. If a query “only” returns ~2,600 rows and you expected more, that’s the site cap, not a bug. Split the query narrower.
  • Danish price formatting. dba.dk uses . as the thousands separator — 24.500 kr. means twenty-four thousand five hundred, not 24.5. The scraper already gives you a clean numeric price, but if you ever parse priceRaw yourself, don’t treat the dot as a decimal point.
  • Detail-page fields are out of scope. No VIN, no full equipment list, no free-text description. If your use case needs those, you’ll need a second pass against detail pages.
  • regNo is optional. Danish number plates only appear when the seller chose to list them; expect this field to be missing on a meaningful share of vehicle rows.
  • Coordinates are approximate. latitude / longitude are town-level, not exact addresses — fine for regional analysis, not for pinpoint mapping.
  • Deduplicate on listingId. If you run overlapping searches (e.g. a brand slice inside a category slice), the same ad can appear in two source searches. Join and dedup on listingId, never on title or URL text.

Wrapping up

DBA.dk is one of the easier European marketplaces to work with — no Cloudflare, datacenter proxy is plenty, and the data comes back typed from the site’s own payload. The only real constraint is the 50-page-per-search cap, which you engineer around by splitting queries narrow. If you need a clean, refreshed feed of Danish listings with prices, seller type, and car specs, the managed actor already handles the redirect split, pagination, dedup, and DKK normalization.

Open the DBA.dk Scraper on Apify — one run turns any dba.dk search into thousands of typed rows: DKK price, location, seller type, and full car specs. No login, no API key, export to JSON / CSV / Excel. Start on Apify’s free monthly credit.

Related guides