DBA.dk Scraper avatar

DBA.dk Scraper

Pricing

Pay per event

Go to Apify Store
DBA.dk Scraper

DBA.dk Scraper

Pricing

Pay per event

Rating

0.0

(0)

Developer

SR

SR

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 hours ago

Last modified

Share

Search Denmark's largest classifieds site and get every ad back as a row: asking price in kroner, the seller's town, how long the ad has been up, whether it ships, and whether the item is used or new.

No login, no cookie, no API key. It reads the ordinary search page a Danish visitor sees, from an exit inside Denmark, so the results are the ones DBA actually serves that market.

What you get

  • Price as a number, parsed out of Danish formatting. 9.800 kr. is nine thousand eight hundred, not nine point eight, and the space before kr. is a non-breaking one that breaks naive parsers
  • Wanted ads separated from offers. Two thirds of the cards on a cheapest-first search are not priced listings at all: Gives væk is a giveaway and Ønsker at købe is someone buying. price_type names which, so a wanted ad never lands in your price average
  • Seller town on every row, which is what turns a price list into a pickup decision
  • Ad age in DBA's own wording (14 t., 5 dage, 1 min.), so you can tell a fresh listing from one that has been sitting for a week
  • Condition and availability joined from the page's own structured data, with the join rate reported rather than assumed
  • buy_now and shipping_ready flags for DBA's Køb nu instant purchase and Fiks færdig managed shipping, which decide whether an ad is transactable or just a phone number
  • Paid placements flagged, not silently mixed in. is_promoted marks them, and because DBA repeats them across pages the walk deduplicates on ad id
  • The search URL from your browser works as input, filters and all
  • A run summary that says what happened: pages fetched, ads returned, how many carried a price, how many were enriched

Why DBA is worth reading

DBA is where Denmark buys and sells second-hand. It is the Danish equivalent of Marktplaats or Kleinanzeigen, and for a large set of categories, bikes, tools, furniture, phones, it is the only liquid market in the country. If you want to know what a used cargo bike actually sells for in Aarhus, DBA is the answer and there is no second source.

The catch is that DBA moved onto Schibsted's recommerce platform, and the move quietly broke the URL everyone had bookmarked. The old /soeg/?soegeord= form still returns HTTP 200 and a megabyte of ads, but on the new path the search term is ignored and what comes back is the homepage. Nothing in the response says so. A scraper built on the old URL returns a full dataset of the wrong ads, and there is no error to catch. This actor uses the canonical path, which is the difference between a working walk and a silent one.

Input

FieldTypeRequiredDefaultWhat it does
querystringone of the twocykelWhat to search for. Danish terms work best
urlstringnoA dba.dk search URL to read instead. Takes precedence
sortselectnorelevanceRelevance, newest, or price ascending/descending
price_minintegernoLower bound in kroner
price_maxintegernoUpper bound in kroner
limitintegerno60Ads to return, 1 to 1000. A page carries about 54
retriesintegerno3Retry attempts per page

Output

{
"position": 4,
"item_id": "24515848",
"url": "https://www.dba.dk/recommerce/forsale/item/24515848",
"title": "TILBUD – CENTURION HELIUM 2026",
"subtitle": "Centurion",
"price": 4890.0,
"price_text": "4.890 kr.",
"price_type": "fixed price",
"currency": "DKK",
"location": "Brønshøj",
"posted_label": "7 min.",
"buy_now": false,
"shipping_ready": false,
"is_promoted": false,
"badges": null,
"condition": "UsedCondition",
"availability": "InStock",
"description": "Centurion Helium 2026, ny model",
"image": "https://images.dbastatic.dk/dynamic/default/item/...",
"enriched": true,
"query": "cykel"
}

Use cases

Pricing your own second-hand stock. Run your category sorted by newest, take the median of price, and you have the number the market is actually asking this week rather than what a guide says. Because posted_label is on every row you can weight fresh listings higher, which matters in categories where prices move.

Watching a specific model. Schedule a narrow query with price_max set to what you would pay, and every run returns only the ads worth acting on. buy_now tells you which of them you can buy immediately instead of negotiating.

Regional price differences. location on every row means you can group by town and see what a Copenhagen listing costs against the same item in Jutland. That spread is the arbitrage that second-hand traders live on, and it is invisible from the site's own interface.

Supply monitoring for a category. Run the same query daily and count rows. A rising count means supply is building and prices are about to soften. Diffing on item_id between runs tells you what is new and what sold.

Finding dealers among the private sellers. Ads with shipping_ready and buy_now set are overwhelmingly traders rather than individuals. Filtering on those two flags is a cheap way to separate the professional supply from the private one.

How it compares

this actorblackfalcondata/dba-listings-scraperthe other seven DBA actors
Per 1.000 ads$1,20$2,00mostly no per-item rate at all
Actor-start fee$0,002$0,01$0,00005 to $0,005
Uses the working search URLyesnot verifiablenot verifiable
Price parsed for Danish formattingyes
Seller townyes
Condition and availabilityyes
Paid placements flagged and deduplicatedyes
Monthly usersnew31 to 2 each

Honest about the other side: blackfalcondata has 1.470 runs behind it and this actor has none, which is a real signal and the only one in that table that favours them. Nine DBA actors exist and none has broken three monthly users, so nobody in this category has proven anything yet.

Pricing

Two events. run_start costs $0,002 per run. listing costs $0,0012 per ad written to the dataset, which is $1,20 per 1.000. Pages that stay blocked or return nothing never reach the dataset and are never billed. All pricing is pay-per-event, with no per-compute-unit charges.

Limits and gotchas

  • The legacy search URL is a trap. dba.dk/soeg/?soegeord=x returns 200 and a page full of ads, but on the current platform the search term is dropped and those are the homepage's ads. If you paste a URL into url, use the /recommerce/forsale/search?q= form, which is what the site's own canonical link points at.
  • A page carries about 54 ads, and one of them is usually paid. Promoted ads repeat across pages, so the ad count you get back is slightly lower than pages × 54 after deduplication. That is correct behaviour, not loss.
  • Condition comes from structured data joined on title. The structured block carries no ad id, so ads with duplicate titles (two ads both called "Cykel") stay unenriched rather than being guessed at. The summary reports how many rows were enriched.
  • A third of cards are not priced offers. The price row holds an amount, Gives væk (a giveaway, reported as 0 kr.) or Ønsker at købe (a wanted ad, where the poster is buying). price_type distinguishes all three plus not stated. Filter to fixed price before averaging anything.
  • Cheapest-first is mostly giveaways. DBA sorts free items ahead of paid ones, so price_asc on a broad term returns a page of Gives væk rows. That is the site's ordering, not a parse failure; the run summary's priceStates shows the split.
  • DBA is Denmark only. Results are Danish, because the site localises by country. There is no country input, because there is no other country.
  • Ad age is a label, not a timestamp. DBA prints 14 t. rather than a date, so posted_label is returned verbatim rather than converted into a time you would have to trust.

FAQ

Can I scrape DBA.dk without an API key? Yes. The search page is served to anonymous visitors and that is what this actor reads. There is no credential field in the input.

Why does my search return the wrong ads? Almost certainly the legacy URL. /soeg/?soegeord= no longer searches on DBA's current platform, and it fails silently. Pass a search term in query and let the actor build the URL, or use the /recommerce/forsale/search?q= form.

How many ads can I get in one run? Up to 1.000, which is about 19 pages. Beyond that, narrow the query or add a price band; deep pagination on a broad term returns increasingly stale ads anyway.

Does it return the seller's name or phone number? No. The search page does not carry them, and this actor reads only the search page. It returns the seller's town, which is what the card shows.

Are prices negotiable prices or final? They are asking prices, and only where price_type is fixed price. buy_now is the flag that tells you the seller has committed to a fixed price you can pay immediately.