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

How to Scrape Imovirtual Portugal Real Estate Data (2026)

Extract Portuguese property listings from Imovirtual — prices, €/m², T-typology, full address and agency data — via its embedded Next.js JSON. No API key.

Imovirtual.com is one of Portugal’s largest property portals and part of the OLX Group, with hundreds of thousands of active listings from Lisboa and Porto down to the Algarve. There’s no open public listings API, so building a Portuguese real-estate dataset usually means scraping the site — and if you go at the rendered HTML, you’ll fight a moving DOM and mild bot protection for every field. Imovirtual is built on Next.js, though, which means every search page ships its full listing data as a server-side JSON blob embedded in the page. Read that blob and you get clean, structured records without rendering a browser. This guide covers what’s in that payload, how the location model works, and the friction you’ll actually hit.

What’s worth extracting

Imovirtual’s embedded __NEXT_DATA__ payload carries a rich record per listing. The useful fields group into a few clusters:

  • Pricingprice (headline price), priceCurrency (EUR), pricePerSqm (€/m²), and monthlyRent (the recurring rent for rentals, returned separately from the headline price).
  • Physical attributesareaSqm (surface area), terrainAreaSqm (plot area), rooms (parsed from the Portuguese T-typology), floor and totalFloors.
  • Full Portuguese addressprovince (distrito), county (concelho / município), city (freguesia / city label), district (bairro) and street. On detail pages, postalCode, latitude and longitude are also available, plus a composed fullAddress.
  • ClassificationpropertyType, estate (the raw enum: FLAT, HOUSE, TERRAIN, COMMERCIAL_PROPERTY, HALL, GARAGE, ROOM, INVESTMENT), market (PRIMARY new-build or SECONDARY resale), transactionType and advertType.
  • Agency & owner dataagencyId, agencyName, agencySlug, agencyLogoUrl, agencyType, contactName, and isPrivate for direct-owner listings.
  • Listing flagsisExclusive, isFeatured, isPromoted, hasOpenDay, plus developmentName and investmentState for primary-market projects.
  • Media & timestampsmainImageUrl, imageUrls, imageCount, totalPossibleImages, dateCreated, dateCreatedFirst and pushedUpAt (last bump).
  • Amenitieslabels, an array of feature tags such as AIR_CONDITIONING, BALCONY, PARKING_SPOT.

For a €/m² study you need price, areaSqm and the address fields. For yield work you also want monthlyRent. The labels array and market flag let you segment by amenity or by new-build vs. resale without extra requests.

How the source actually works

Imovirtual belongs to the same OLX Group platform family as Otodom (Poland) and shares the same Next.js server-side rendering model. Each search results page embeds its listing data in a __NEXT_DATA__ script tag. The scraper fetches the page over plain HTTP, parses that JSON, and emits one row per listing — no browser, no GraphQL token, no DOM walking.

Locations are addressed through URL slugs that follow Portugal’s administrative hierarchy (distrito → concelho → freguesia):

  • District: lisboa, porto, faro, braga, setubal
  • Council: lisboa/cascais
  • Parish: lisboa/cascais/cascais-e-estoril
  • All of Portugal: todo-o-pais

To find a slug, browse imovirtual.com, apply a location filter, and copy the path between /resultados/{transaction}/{type}/ and the ? in the URL. A realistic run — Lisbon and Porto apartments for sale — looks like this:

{
  "locationSlugs": ["lisboa", "porto"],
  "transaction": "sale",
  "propertyType": "apartment",
  "priceMin": 200000,
  "priceMax": 600000,
  "areaMin": 50,
  "areaMax": 120,
  "roomsMin": 2,
  "roomsMax": 3,
  "market": "SECONDARY",
  "ownerType": "ALL",
  "sort": "latest",
  "limit": 72,
  "maxListings": 500,
  "maxPagesPerTask": 10,
  "requestDelay": 800,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "PT" }
}

Each entry in locationSlugs becomes its own task, so you can benchmark several cities in one run and every row is tagged with its searchLocation. Property types cover apartment, house, plot, commercial, warehouse, garage, room, development and studio. The distanceRadius option (0, 5, 10, 15, 25, 50 or 75 km) expands a search into neighboring areas, and limit sets page size to 24, 36, 48 or 72.

Run the Imovirtual Scraper on Apify — one run pulls thousands of Portuguese listings with price, €/m², T-typology, full district/council/parish address and agency data. No API key, no login. Export to JSON, CSV, Excel or XML.

The access reality

No key or login is required, but Imovirtual deploys mild bot protection, so a few things matter:

  • Datacenter IPs get blocked. Plain datacenter proxies frequently draw a block. Residential Apify Proxy with apifyProxyCountry: "PT" is strongly recommended for reliable access.
  • Pace requests. Keep requestDelay at 600 ms or higher. The scraper runs cleanly at that pace; faster invites throttling.
  • Rotate on failure. maxRetries rotates the proxy IP on HTTP errors so a transient block doesn’t kill the whole task.
  • Deep pagination needs narrowing. Imovirtual paginates large filter sets, but the deepest inventory is easier to reach by narrowing with price and area filters than by paging endlessly through one broad query. Split by price band or drill into a council slug for dense markets.
  • GPS and postal code are detail-page only. The search-results JSON gives you the full administrative breakdown (province/county/city) but not exact coordinates. latitude, longitude and postalCode populate on detail pages. If you don’t need door-level positioning, the parish-level address is enough for most analysis.

The reason not to scrape the rendered HTML is the same as with any Next.js site: the listings you want are already in the page as JSON before the DOM finishes hydrating. Parsing __NEXT_DATA__ is both faster and far more stable than chasing CSS selectors that change with every front-end release.

Example output

One representative record (trimmed) from a Lisbon sale search:

{
  "adId": "68812345",
  "detailUrl": "https://www.imovirtual.com/pt/anuncio/apartamento-t2-lisboa-...",
  "title": "Apartamento T2 · Lisboa, Alvalade",
  "transactionType": "sale",
  "propertyType": "apartment",
  "estate": "FLAT",
  "market": "SECONDARY",
  "price": 385000,
  "priceCurrency": "EUR",
  "pricePerSqm": 5138,
  "areaSqm": 75,
  "rooms": 2,
  "province": "Lisboa",
  "county": "Lisboa",
  "city": "Alvalade",
  "advertType": "AGENCY",
  "agencyId": "12345",
  "agencyName": "Prime Imobiliária",
  "isExclusive": true,
  "labels": ["BALCONY", "AIR_CONDITIONING", "PARKING_SPOT"],
  "dateCreated": "2026-07-03",
  "scrapedAt": "2026-07-06T12:00:00Z"
}

Use cases

What Portuguese property data at this granularity supports:

  • €/m² market research — build price-per-square-meter heatmaps by distrito, concelho and freguesia. pricePerSqm is already parsed per listing.
  • Investment screening — scrape both sale and rent, then compute rental yield (monthlyRent against comparable price) per area, from Lisboa and Porto to the Algarve.
  • Lead generation — set ownerType: "PRIVATE" to find direct-owner listings, or cluster agency listings by agencyId to map the most active agencies in a market.
  • Price and activity tracking — re-run on a schedule and diff against prior datasets using dateCreated and pushedUpAt to detect price changes and re-listings.
  • Primary-market monitoring — use propertyType: "development" or market: "PRIMARY" to track new developer offers and their investmentState.
  • Cross-city comparison — pass multiple locationSlugs in one run to benchmark prices and inventory across Portuguese cities.

Build-it-yourself vs. managed actor

Parsing __NEXT_DATA__ yourself is feasible — the payload is right there in the HTML. What accumulates:

  • Portuguese residential proxy. Datacenter IPs get blocked, so you need a residential PT pool (a few hundred dollars a month for a decent one). The managed actor bundles Apify residential proxy and charges per row.
  • Slug and pagination handling. You’ll replicate the distrito/concelho/freguesia slug logic and the pagination cursor, and keep them working as the site evolves.
  • T-typology parsing. Portuguese listings encode bedroom count as T0T10; you need to parse that into a numeric field. The actor already maps it into rooms.
  • Rotation and retry. Getting IP rotation to fire on the right responses at a polite pace is the usual time sink.

The managed actor is pay-per-result — a few thousand listings across several cities lands in the low single dollars including proxy. The real saving is skipping the reverse-engineering of the OLX-family payload shape and the proxy tuning before you see your first clean row.

Common pitfalls

Specific gotchas for Imovirtual data:

  • Rent lives in a separate field. For rentals, read monthlyRent, not just price. Branch on transactionType before aggregating so you never mix rents into sale-price averages.
  • T-typology counts bedrooms, not rooms. T2 means two bedrooms, not two total rooms — rooms reflects the T-number. Filter with roomsMin/roomsMax accordingly and don’t confuse it with total-room counts from other portals.
  • estate vs. propertyType. propertyType is the friendly type; estate is the raw enum (FLAT, HOUSE, TERRAIN, …). If you’re joining across sources, key on the raw enum, which is stable.
  • Coordinates require detail pages. Don’t expect latitude/longitude or postalCode from a results-page scrape — those are detail-page fields. Use province/county/city for spatial grouping.
  • Promoted/featured listings repeat. isPromoted and isFeatured ads can appear at the top of multiple pages. Dedup on adId so a boosted listing isn’t counted several times.
  • Primary-market listings differ. New-build (PRIMARY) entries may carry a developmentName and investmentState and behave differently from resale stock — segment on market before you compare prices.

Wrapping up

For a single city snapshot, parsing __NEXT_DATA__ with a Portuguese residential IP is a reasonable weekend project. For a refreshed, multi-region Portuguese property feed — for yield models, market dashboards or agency lead lists — a managed actor that already solves the slug model, proxy and rotation problems will get you to clean rows in minutes instead of days.

Open the Imovirtual Scraper on Apify — reads Imovirtual’s embedded __NEXT_DATA__ JSON to return price, €/m², T-typology, full Portuguese address, agency data and image galleries per listing. No API key, no login, residential-PT proxy ready. Export to JSON, CSV, Excel or XML. Start on Apify’s free monthly credit.

Related guides