Sign inTry it

Search flats and houses to rent or buy in Poland on Otodom.

Searches Otodom, Poland's largest property portal, in one of the 12 biggest cities: flats, houses or rooms to rent or for sale, by price, area, rooms (flats) and sort. Each listing has the price in PLN (and the monthly fees / czynsz), price per m², area, rooms, floor, street and district, private or agency, when it was listed, a photo and the link. Promoted listings are dropped by default.

No reports yetRead-only, no login
Site
Otodom, Poland
Version
v2 of 2
Runs, last 7 days
No reports yet
sha256
38f3edd1ee8a…

Run it with your agent

after installing Wield

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

“Search flats and houses to rent or buy in Poland on Otodom.”

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

{
  "tool": "run",
  "arguments": {
    "recipe_id": "otodom.pl/search-properties",
    "params": {
      "city": "warszawa",
      "max_price": 4000,
      "rooms": 2
    }
  }
}

Requests

sent from your browser, in order
  1. 1GET/pl/wyniki/{{f.tx}}/{{f.estate}}/{{f.loc}}?areaMax&areaMin&by&direction&page&priceMax&priceMinThe server-rendered results page /pl/wyniki/<wynajem|sprzedaz>/<mieszkanie[,N-pokoje]|dom|pokoj>/<location id> (Next.js; __NEXT_DATA__ props.pageProps.data.searchAds). The one-item foreach maps the city to Otodom's location id and builds the path and sort.repeats, max 1

Parameters

from your agent
cityenumrequiredwarszawa, krakow, wroclaw, lodz, poznan, gdansk, gdynia, szczecin, katowice, lublin, bialystok or bydgoszcz "warszawa" | "krakow" | "wroclaw" | "lodz" | "poznan" | "gdansk" | "gdynia" | "szczecin" | "katowice" | "lublin" | "bialystok" | "bydgoszcz"
include_promotedbooleanKeep promoted listings, marked = false
max_areaintegerm²
max_priceintegerPLN (per month when renting)
min_areaintegerm²
min_priceintegerPLN (per month when renting)
pageinteger36 listings per page = 1
property_typeenum "flat" | "house" | "room" = "flat"
roomsenumFlats only: exactly this many rooms 2 | 3 | 4
sortenum "relevance" | "newest" | "price_low" | "price_high" = "relevance"
transactionenum "rent" | "buy" = "rent"

Returns

to your agent
citystring
listingsobject[]agency, area_m2, bumped_at, city, development, district, fees_pln, floor, id, image, listed, price_per_m2_pln, price_pln, private_owner, promoted, rooms, street, title, url
pageinteger
totalinteger
transactionstring

Where it can send

  • www.otodom.pl

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) > `15`
  • output.total > `100`
  • length(output.listings[?promoted]) == `0`
  • length(output.listings[?price_pln > `4000`]) == `0`
  • length(output.listings[?rooms != `null` && rooms != `2`]) == `0`
  • length(output.listings[?starts_with(url, 'https://www.otodom.pl/pl/oferta/') && city == 'Warszawa']) > `15`

Raw recipe

Served as canonical JSON from /api/v1/recipes/otodom.pl/search-properties, so its sha256 matches the ETag and the index.

Check it yourself
curl -s https://wield.run/api/v1/recipes/otodom.pl/search-properties | shasum -a 256
# 38f3edd1ee8aac25e855d62e375ee956ccbe8c557d0aa1976314760e029f0674
otodom.pl/search-properties.json, v2
{
  "description": "Searches Otodom, Poland's largest property portal, in one of the 12 biggest cities: flats, houses or rooms to rent or for sale, by price, area, rooms (flats) and sort. Each listing has the price in PLN (and the monthly fees / czynsz), price per m², area, rooms, floor, street and district, private or agency, when it was listed, a photo and the link. Promoted listings are dropped by default.",
  "effect": "read",
  "id": "otodom.pl/search-properties",
  "keywords": [
    "otodom",
    "mieszkanie",
    "wynajem",
    "sprzedaż",
    "dom",
    "pokój",
    "nieruchomości",
    "czynsz",
    "warszawa",
    "kraków",
    "wrocław",
    "gdańsk",
    "poznań",
    "flat",
    "apartment",
    "rent",
    "buy",
    "poland",
    "property",
    "real estate"
  ],
  "output": {
    "schema": {
      "properties": {
        "city": {
          "type": "string"
        },
        "listings": {
          "items": {
            "properties": {
              "agency": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "area_m2": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "bumped_at": {
                "description": "When the advertiser last paid to push it up",
                "type": [
                  "string",
                  "null"
                ]
              },
              "city": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "development": {
                "description": "A new-build development (inwestycja)",
                "type": "boolean"
              },
              "district": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "fees_pln": {
                "description": "Monthly fees (czynsz) where given",
                "type": [
                  "number",
                  "null"
                ]
              },
              "floor": {
                "description": "0 ground floor, -1 cellar, 11 above the tenth, 99 attic",
                "type": [
                  "integer",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "image": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "listed": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "price_per_m2_pln": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "price_pln": {
                "description": "Rent per month or sale price; null for new developments that show a price per m² only",
                "type": [
                  "number",
                  "null"
                ]
              },
              "private_owner": {
                "type": "boolean"
              },
              "promoted": {
                "type": "boolean"
              },
              "rooms": {
                "description": "11 = more than 10",
                "type": [
                  "integer",
                  "null"
                ]
              },
              "street": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "title": {
                "type": "string"
              },
              "url": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "type": "array"
        },
        "page": {
          "type": "integer"
        },
        "total": {
          "type": [
            "integer",
            "null"
          ]
        },
        "transaction": {
          "type": "string"
        }
      },
      "required": [
        "city",
        "transaction",
        "listings"
      ],
      "type": "object"
    },
    "value": "let $promo = params.include_promoted == `true`, $num = items(`{\"ONE\":1,\"TWO\":2,\"THREE\":3,\"FOUR\":4,\"FIVE\":5,\"SIX\":6,\"SEVEN\":7,\"EIGHT\":8,\"NINE\":9,\"TEN\":10,\"MORE\":11}`), $fl = items(`{\"CELLAR\":-1,\"GROUND\":0,\"FIRST\":1,\"SECOND\":2,\"THIRD\":3,\"FOURTH\":4,\"FIFTH\":5,\"SIXTH\":6,\"SEVENTH\":7,\"EIGHTH\":8,\"NINTH\":9,\"TENTH\":10,\"ABOVE_TENTH\":11,\"GARRET\":99}`) in {city: params.city, transaction: params.transaction || 'rent', total: steps.search[0].total || `0`, page: params.page || `1`, listings: map(&(let $a = @ in let $geo = $a.location.reverseGeocoding.locations || `[]` in {id: to_string($a.id), title: $a.title, price_pln: $a.hidePrice != `true` && $a.totalPrice.value || `null`, fees_pln: $a.rentPrice.value || `null`, price_per_m2_pln: $a.pricePerSquareMeter.value || $a.priceFromPerSquareMeter.value || `null`, area_m2: $a.areaInSquareMeters || `null`, rooms: ($num[?[0] == $a.roomsNumber] | [0][1]) || `null`, floor: ($fl[?[0] == $a.floorNumber] | [0][1]) || `null`, street: $a.location.address.street.name || `null`, district: ($geo[?locationLevel == 'district'] | [0].name) || `null`, city: ($geo[?locationLevel == 'city_or_village'] | [0].name) || `null`, private_owner: $a.isPrivateOwner == `true`, agency: $a.agency.name && trim($a.agency.name) || `null`, development: $a.estate == 'INVESTMENT', listed: $a.createdAtFirst || $a.dateCreated || `null`, bumped_at: $a.pushedUpAt || `null`, promoted: $a.isPromoted == `true`, image: $a.images[0].medium || `null`, url: join('', ['https://www.otodom.pl/pl/oferta/', $a.slug])}), steps.search[0].items || `[]`)[?$promo || !promoted]}"
  },
  "params": {
    "additionalProperties": false,
    "properties": {
      "city": {
        "description": "warszawa, krakow, wroclaw, lodz, poznan, gdansk, gdynia, szczecin, katowice, lublin, bialystok or bydgoszcz",
        "enum": [
          "warszawa",
          "krakow",
          "wroclaw",
          "lodz",
          "poznan",
          "gdansk",
          "gdynia",
          "szczecin",
          "katowice",
          "lublin",
          "bialystok",
          "bydgoszcz"
        ],
        "type": "string"
      },
      "include_promoted": {
        "default": false,
        "description": "Keep promoted listings, marked",
        "type": "boolean"
      },
      "max_area": {
        "description": "m²",
        "minimum": 0,
        "type": "integer"
      },
      "max_price": {
        "description": "PLN (per month when renting)",
        "minimum": 0,
        "type": "integer"
      },
      "min_area": {
        "description": "m²",
        "minimum": 0,
        "type": "integer"
      },
      "min_price": {
        "description": "PLN (per month when renting)",
        "minimum": 0,
        "type": "integer"
      },
      "page": {
        "default": 1,
        "description": "36 listings per page",
        "maximum": 50,
        "minimum": 1,
        "type": "integer"
      },
      "property_type": {
        "default": "flat",
        "enum": [
          "flat",
          "house",
          "room"
        ],
        "type": "string"
      },
      "rooms": {
        "description": "Flats only: exactly this many rooms",
        "enum": [
          2,
          3,
          4
        ],
        "type": "integer"
      },
      "sort": {
        "default": "relevance",
        "enum": [
          "relevance",
          "newest",
          "price_low",
          "price_high"
        ],
        "type": "string"
      },
      "transaction": {
        "default": "rent",
        "enum": [
          "rent",
          "buy"
        ],
        "type": "string"
      }
    },
    "required": [
      "city"
    ],
    "type": "object"
  },
  "provenance": {
    "method": "browser-inspect",
    "notes": "Otodom's results pages are server-rendered by Next.js: __NEXT_DATA__ props.pageProps.data.searchAds has 36 items per page and pagination.totalItems. Location ids are voivodeship/powiat/gmina/city (mazowieckie/warszawa/warszawa/warszawa); the 12 here were each checked live (200 with that location and thousands of ads). The site's own location search is a lazily loaded GraphQL query, so the recipe uses this fixed list. A rooms filter is part of the path (mieszkanie,3-pokoje); the query form roomsNumber=[TWO] 307-redirects to it, and a 1-room path does not exist (it redirects without the filter). priceMin/priceMax/areaMin/areaMax, by/direction (LATEST, PRICE) and page are query parameters. isPromoted listings are paid placements (dropped by default); pushedUpAt is a paid bump of a genuine listing (kept, shown). Advertiser names of private persons are left out. Answers servers. v2 (2026-11-07 22:38): tos.notes only; requests and output unchanged.",
    "recorded_at": "2026-11-07T22:08:00+01:00",
    "recorded_by": "C4"
  },
  "requires_login": false,
  "schema": "https://wield.run/schema/recipe/v1.json",
  "site": {
    "country": "PL",
    "id": "otodom.pl",
    "language": "pl",
    "name": "Otodom",
    "origin": "https://www.otodom.pl",
    "origins": [
      "https://www.otodom.pl"
    ]
  },
  "steps": [
    {
      "description": "The server-rendered results page /pl/wyniki/<wynajem|sprzedaz>/<mieszkanie[,N-pokoje]|dom|pokoj>/<location id> (Next.js; __NEXT_DATA__ props.pageProps.data.searchAds). The one-item foreach maps the city to Otodom's location id and builds the path and sort.",
      "expect": {
        "content_type": "html",
        "status": [
          200
        ]
      },
      "extract": {
        "embedded_json": {
          "selector": "script#__NEXT_DATA__",
          "vars": {
            "items": "props.pageProps.data.searchAds.items",
            "total": "props.pageProps.data.searchAds.pagination.totalItems"
          }
        }
      },
      "foreach": {
        "as": "f",
        "in": "[{tx: params.transaction == 'buy' && 'sprzedaz' || 'wynajem', estate: join('', [(params.property_type == 'house' && 'dom') || (params.property_type == 'room' && 'pokoj') || 'mieszkanie', (params.property_type != 'house' && params.property_type != 'room' && params.rooms) && join('', [',', to_string(params.rooms), '-pokoje']) || '']), loc: (let $c = params.city in items(`{\"warszawa\":\"mazowieckie/warszawa/warszawa/warszawa\",\"krakow\":\"malopolskie/krakow/krakow/krakow\",\"wroclaw\":\"dolnoslaskie/wroclaw/wroclaw/wroclaw\",\"lodz\":\"lodzkie/lodz/lodz/lodz\",\"poznan\":\"wielkopolskie/poznan/poznan/poznan\",\"gdansk\":\"pomorskie/gdansk/gdansk/gdansk\",\"gdynia\":\"pomorskie/gdynia/gdynia/gdynia\",\"szczecin\":\"zachodniopomorskie/szczecin/szczecin/szczecin\",\"katowice\":\"slaskie/katowice/katowice/katowice\",\"lublin\":\"lubelskie/lublin/lublin/lublin\",\"bialystok\":\"podlaskie/bialystok/bialystok/bialystok\",\"bydgoszcz\":\"kujawsko--pomorskie/bydgoszcz/bydgoszcz/bydgoszcz\"}`)[?[0] == $c] | [0][1]), by: (params.sort == 'newest' && 'LATEST') || ((params.sort == 'price_low' || params.sort == 'price_high') && 'PRICE') || `null`, dir: (params.sort == 'newest' && 'DESC') || (params.sort == 'price_low' && 'ASC') || (params.sort == 'price_high' && 'DESC') || `null`, page: (params.page || `1`) > `1` && to_string(params.page) || `null`}]",
        "max": 1
      },
      "id": "search",
      "parse": "html",
      "request": {
        "headers": {
          "Accept": "text/html"
        },
        "method": "GET",
        "query": {
          "areaMax": "{{params.max_area}}",
          "areaMin": "{{params.min_area}}",
          "by": "{{f.by}}",
          "direction": "{{f.dir}}",
          "page": "{{f.page}}",
          "priceMax": "{{params.max_price}}",
          "priceMin": "{{params.min_price}}"
        },
        "url": "/pl/wyniki/{{f.tx}}/{{f.estate}}/{{f.loc}}"
      }
    }
  ],
  "task": "Search flats and houses to rent or buy in Poland on Otodom",
  "tos": {
    "notes": "Otodom's robots.txt sets Content-Signal ai-input=no and ai-train=no. Wield runs it only when the user asks, in the user's own browser, one search page per call: no bulk collection, no contact with advertisers. Terms not reviewed yet for automated access. One person's search: 1 request for one results page, as a visitor gets it. robots.txt allows /pl/wyniki/. Contacting advertisers stays on otodom.pl.",
    "reviewed": false
  },
  "verify": {
    "checks": [
      "length(output.listings) > `15`",
      "output.total > `100`",
      "length(output.listings[?promoted]) == `0`",
      "length(output.listings[?price_pln > `4000`]) == `0`",
      "length(output.listings[?rooms != `null` && rooms != `2`]) == `0`",
      "length(output.listings[?starts_with(url, 'https://www.otodom.pl/pl/oferta/') && city == 'Warszawa']) > `15`"
    ],
    "example_params": {
      "city": "warszawa",
      "max_price": 4000,
      "rooms": 2
    },
    "max_ms": 6000
  },
  "version": 2
}