DBA.dk Scraper
Pricing
Pay per event
DBA.dk Scraper
Pricing
Pay per event
Rating
0.0
(0)
Developer
SR
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 hours ago
Last modified
Categories
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 beforekr.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ækis a giveaway andØnsker at købeis someone buying.price_typenames 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_nowandshipping_readyflags 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_promotedmarks 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
| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
query | string | one of the two | cykel | What to search for. Danish terms work best |
url | string | no | – | A dba.dk search URL to read instead. Takes precedence |
sort | select | no | relevance | Relevance, newest, or price ascending/descending |
price_min | integer | no | – | Lower bound in kroner |
price_max | integer | no | – | Upper bound in kroner |
limit | integer | no | 60 | Ads to return, 1 to 1000. A page carries about 54 |
retries | integer | no | 3 | Retry 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 actor | blackfalcondata/dba-listings-scraper | the other seven DBA actors | |
|---|---|---|---|
| Per 1.000 ads | $1,20 | $2,00 | mostly no per-item rate at all |
| Actor-start fee | $0,002 | $0,01 | $0,00005 to $0,005 |
| Uses the working search URL | yes | not verifiable | not verifiable |
| Price parsed for Danish formatting | yes | – | – |
| Seller town | yes | – | – |
| Condition and availability | yes | – | – |
| Paid placements flagged and deduplicated | yes | – | – |
| Monthly users | new | 3 | 1 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=xreturns 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 intourl, 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_typedistinguishes all three plusnot stated. Filter tofixed pricebefore averaging anything. - Cheapest-first is mostly giveaways. DBA sorts free items ahead of paid ones, so
price_ascon a broad term returns a page ofGives vækrows. That is the site's ordering, not a parse failure; the run summary'spriceStatesshows 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, soposted_labelis 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.
Related Actors
- Marktplaats Scraper — the same job for the Dutch classifieds market
- Willhaben Scraper — Austrian classifieds across four verticals
- Vinted Scraper — second-hand fashion across nine European markets