Sign inTry it

Search 2dehands listings by price, distance and date.

Searches 2dehands (2ememain), Belgium's largest classifieds site, like its search: title, short description, price in euros and price type (fixed, bidding, free, …), condition, city, distance from a postcode, when it was listed, seller and whether verified, pickup or shipping, promoted flag, image and link. Sort by relevance, newest, price or distance. Business ads are dropped by default.

No reports yetRead-only, no login
Site
2dehands, Belgium
Version
v1
Runs, last 7 days
No reports yet
sha256
d7759cba433d…

Run it with your agent

after installing Wield

Ask in plain words. Your agent finds this recipe and calls it:

“Search 2dehands listings by price, distance and date.”

Read-only: it changes nothing on the site. No login needed.

{
  "tool": "run",
  "arguments": {
    "recipe_id": "2dehands.be/search-listings",
    "params": {
      "max_price": 300,
      "query": "fiets",
      "sort": "newest"
    }
  }
}

Requests

sent from your browser, in order
  1. 1GET/lrp/api/search?attributeRanges[]&distanceMeters&limit&offset&postcode&query&sortBy&sortOrder&viewOptions2dehands's own search API (the list page calls it when filters change). The one-item foreach builds the price range, sort and offset.repeats, max 1

Parameters

from your agent
distance_kmenumOnly with postcode 3 | 5 | 10 | 15 | 25 | 50 | 75
include_adsbooleanKeep business ads (marked sponsored) = false
max_pricenumberEUR
min_pricenumberEUR
pageinteger = 1
postcodestringBelgian postcode for distance, e.g. '9000' (Gent)
querystringrequiredWhat to look for, e.g. 'fiets', 'bakfiets', 'vélo électrique'
sortenum "relevance" | "newest" | "price_low" | "price_high" | "distance" = "relevance"

Returns

to your agent
listingsobject[]city, condition, delivery, description, distance_km, id, image, latitude, listed, longitude, price_eur, price_type, promoted, seller, seller_verified, sponsored, title, url
pageinteger
querystring
totalinteger

Where it can send

  • www.2dehands.be

Anything else is blocked by the extension.

Reads from your session

Nothing. Your browser attaches the site's cookies by itself.

Used only in requests to the addresses on the left. Never sent to wield.run or your agent.

Checks

a run passes when
  • length(output.listings) > `10`
  • length(output.listings[?sponsored]) == `0`
  • length(output.listings[?price_eur > `300`]) == `0`
  • length(output.listings[?starts_with(url, 'https://www.2dehands.be/v/')]) == length(output.listings)
  • output.total > `100`

Raw recipe

Served as canonical JSON from /api/v1/recipes/2dehands.be/search-listings, so its sha256 matches the ETag and the index.

Check it yourself
curl -s https://wield.run/api/v1/recipes/2dehands.be/search-listings | shasum -a 256
# d7759cba433d9cd7e8686874904228a8dbeaaa9236629cc12e5f952ff67f3136
2dehands.be/search-listings.json, v1
{
  "description": "Searches 2dehands (2ememain), Belgium's largest classifieds site, like its search: title, short description, price in euros and price type (fixed, bidding, free, …), condition, city, distance from a postcode, when it was listed, seller and whether verified, pickup or shipping, promoted flag, image and link. Sort by relevance, newest, price or distance. Business ads are dropped by default.",
  "effect": "read",
  "id": "2dehands.be/search-listings",
  "keywords": [
    "2dehands",
    "2ememain",
    "tweedehands",
    "seconde main",
    "kopen",
    "verkopen",
    "acheter",
    "vendre",
    "fiets",
    "vélo",
    "gebruikt",
    "occasion",
    "zoekertjes",
    "annonces",
    "classifieds",
    "belgium",
    "used",
    "marketplace"
  ],
  "output": {
    "schema": {
      "properties": {
        "listings": {
          "items": {
            "properties": {
              "city": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "condition": {
                "description": "As the seller states it, e.g. 'Zo goed als nieuw', 'Nieuw', 'Gebruikt'",
                "type": [
                  "string",
                  "null"
                ]
              },
              "delivery": {
                "description": "Ophalen (pickup), Verzenden (shipping) or both",
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "distance_km": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "image": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "latitude": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "listed": {
                "description": "As 2dehands shows it, e.g. 'Vandaag', '3 nov 26'",
                "type": [
                  "string",
                  "null"
                ]
              },
              "longitude": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "price_eur": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "price_type": {
                "description": "FIXED, BIDDING (bieden), FREE, SEE_DESCRIPTION, …",
                "type": [
                  "string",
                  "null"
                ]
              },
              "promoted": {
                "description": "The seller paid for a boost (e.g. Dagtopper)",
                "type": "boolean"
              },
              "seller": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "seller_verified": {
                "type": "boolean"
              },
              "sponsored": {
                "description": "Business ad (Admarkt)",
                "type": "boolean"
              },
              "title": {
                "type": "string"
              },
              "url": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "type": "array"
        },
        "page": {
          "type": "integer"
        },
        "query": {
          "type": "string"
        },
        "total": {
          "type": [
            "integer",
            "null"
          ]
        }
      },
      "type": "object"
    },
    "value": "let $ads = params.include_ads == `true` in {query: params.query, total: steps.search[0].total || `null`, page: params.page || `1`, listings: map(&(let $l = @ in {id: $l.itemId, title: $l.title, description: $l.description || `null`, price_eur: ($l.priceInfo.priceCents > `0` && $l.priceInfo.priceCents / `100`) || (($l.priceInfo.priceType == 'FREE') && `0`) || `null`, price_type: $l.priceInfo.priceType || `null`, condition: ($l.attributes[?key == 'condition'] | [0].value) || `null`, city: $l.location.cityName || `null`, distance_km: ($l.location.distanceMeters >= `0` && $l.location.distanceMeters / `1000`) || `null`, latitude: $l.location.latitude || `null`, longitude: $l.location.longitude || `null`, listed: $l.date || `null`, seller: $l.sellerInformation.sellerName || `null`, seller_verified: $l.sellerInformation.isVerified == `true`, delivery: ($l.attributes[?key == 'delivery'] | [0].value) || `null`, promoted: $l.priorityProduct != 'NONE' && $l.priorityProduct != `null`, sponsored: starts_with($l.itemId, 'a') || contains($l.traits || `[]`, 'ADMARKT_CONSOLE'), image: ($l.pictures[0].mediumUrl && (starts_with($l.pictures[0].mediumUrl, '//') && join('', ['https:', $l.pictures[0].mediumUrl]) || $l.pictures[0].mediumUrl)) || `null`, url: join('', ['https://www.2dehands.be', $l.vipUrl])}), steps.search[0].listings || `[]`)[?$ads || !sponsored]}"
  },
  "params": {
    "additionalProperties": false,
    "properties": {
      "distance_km": {
        "description": "Only with postcode",
        "enum": [
          3,
          5,
          10,
          15,
          25,
          50,
          75
        ],
        "type": "integer"
      },
      "include_ads": {
        "default": false,
        "description": "Keep business ads (marked sponsored)",
        "type": "boolean"
      },
      "max_price": {
        "description": "EUR",
        "minimum": 0,
        "type": "number"
      },
      "min_price": {
        "description": "EUR",
        "minimum": 0,
        "type": "number"
      },
      "page": {
        "default": 1,
        "maximum": 20,
        "minimum": 1,
        "type": "integer"
      },
      "postcode": {
        "description": "Belgian postcode for distance, e.g. '9000' (Gent)",
        "pattern": "^[1-9][0-9]{3}$",
        "type": "string"
      },
      "query": {
        "description": "What to look for, e.g. 'fiets', 'bakfiets', 'vélo électrique'",
        "maxLength": 100,
        "minLength": 2,
        "type": "string"
      },
      "sort": {
        "default": "relevance",
        "enum": [
          "relevance",
          "newest",
          "price_low",
          "price_high",
          "distance"
        ],
        "type": "string"
      }
    },
    "required": [
      "query"
    ],
    "type": "object"
  },
  "provenance": {
    "method": "browser-inspect",
    "notes": "Same Adevinta platform as marktplaats.nl (recipe marktplaats.nl/search-listings): the list page calls /lrp/api/search with query, limit, offset, sortBy (OPTIMIZED, SORT_INDEX, PRICE, LOCATION), sortOrder, attributeRanges[]=PriceCents:<min|null>:<max|null>, postcode (4 digits) and distanceMeters. Business ads: itemId starting with 'a' or trait ADMARKT_CONSOLE. Paid boosts of genuine listings (priorityProduct) are kept and marked promoted. Condition comes from the listing attribute 'condition'. Answers servers. 2ememain.be is the French-language front of the same listings.",
    "recorded_at": "2026-11-07T21:52:00+01:00",
    "recorded_by": "C4"
  },
  "requires_login": false,
  "schema": "https://wield.run/schema/recipe/v1.json",
  "site": {
    "country": "BE",
    "id": "2dehands.be",
    "language": "nl",
    "name": "2dehands",
    "origin": "https://www.2dehands.be",
    "origins": [
      "https://www.2dehands.be"
    ]
  },
  "steps": [
    {
      "description": "2dehands's own search API (the list page calls it when filters change). The one-item foreach builds the price range, sort and offset.",
      "expect": {
        "assert": "body.listings != `null`",
        "content_type": "json",
        "status": [
          200
        ]
      },
      "extract": {
        "json": {
          "listings": "listings",
          "total": "totalResultCount"
        }
      },
      "foreach": {
        "as": "f",
        "in": "[{offset: (params.page - `1`) * `30`, range: (params.min_price || params.max_price) && join('', ['PriceCents:', params.min_price && to_string(floor(params.min_price * `100`)) || 'null', ':', params.max_price && to_string(floor(params.max_price * `100`)) || 'null']) || `null`, sortBy: (params.sort == 'newest' && 'SORT_INDEX') || ((params.sort == 'price_low' || params.sort == 'price_high') && 'PRICE') || (params.sort == 'distance' && 'LOCATION') || 'OPTIMIZED', sortOrder: (params.sort == 'newest' && 'DECREASING') || (params.sort == 'price_high' && 'DECREASING') || 'INCREASING', postcode: params.postcode || `null`, distance: params.postcode && params.distance_km && to_string(params.distance_km * `1000`) || `null`}]",
        "max": 1
      },
      "id": "search",
      "request": {
        "headers": {
          "Accept": "application/json"
        },
        "method": "GET",
        "query": {
          "attributeRanges[]": "{{f.range}}",
          "distanceMeters": "{{f.distance}}",
          "limit": "30",
          "offset": "{{f.offset}}",
          "postcode": "{{f.postcode}}",
          "query": "{{params.query}}",
          "sortBy": "{{f.sortBy}}",
          "sortOrder": "{{f.sortOrder}}",
          "viewOptions": "list-view"
        },
        "url": "/lrp/api/search"
      }
    }
  ],
  "task": "Search 2dehands listings by price, distance and date",
  "tos": {
    "notes": "One search request per call, the same one the list page makes. robots.txt disallows /lrp/api/search* for bots (unlike marktplaats.nl), so the daily server health check skips it and health comes from run telemetry. No messages, no bids.",
    "reviewed": false
  },
  "verify": {
    "checks": [
      "length(output.listings) > `10`",
      "length(output.listings[?sponsored]) == `0`",
      "length(output.listings[?price_eur > `300`]) == `0`",
      "length(output.listings[?starts_with(url, 'https://www.2dehands.be/v/')]) == length(output.listings)",
      "output.total > `100`"
    ],
    "example_params": {
      "max_price": 300,
      "query": "fiets",
      "sort": "newest"
    },
    "max_ms": 3000
  },
  "version": 1
}