# Imovirtual Scraper - Portugal Property Listings & Agents (`sian.agency/imovirtual-property-scraper`) Actor

Scrape Imovirtual.com property listings across Portugal with GPS coordinates, energy certificate, build year, agency phone numbers and the full advert text — not just the search-card summary.

- **URL**: https://apify.com/sian.agency/imovirtual-property-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** Real estate, Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.20 / 1,000 property searches

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Imovirtual Scraper - Portugal Property Listings & Agents 🚀

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Idealista](https://img.shields.io/badge/Store-Idealista%20Scraper-E60023)](https://apify.com/sian.agency/smart-idealista-scraper?fpr=sian) [![Otodom](https://img.shields.io/badge/Store-Otodom%20Property-1AE392)](https://apify.com/sian.agency/otodom-property-scraper?fpr=sian) [![Fotocasa](https://img.shields.io/badge/Store-Fotocasa%20Property-1AE392)](https://apify.com/sian.agency/fotocasa-property-scraper?fpr=sian)

#### 🎉 Goes one page deeper than the search card: GPS coordinates, energy certificate, build year and the advertiser's phone on every listing

##### For valuation teams, buyer's agents and anyone building a Portuguese property dataset that has to hold up

***

### 🔎 What is the Imovirtual Portugal Property Scraper — and when should you use it?

The **Imovirtual Portugal Property Scraper** turns public Imovirtual.com property listings from anywhere in Portugal into clean, structured rows you can filter, export and feed straight into a spreadsheet, database or AI agent. No account, no portal API key, no browser automation to maintain.

**Use it when you need:** Portuguese sale and rental adverts as rows: asking price or monthly rent in euros, price per square metre, floor and plot area, the T0-T4+ typology Portuguese buyers actually search, floor, and location down to district, council, parish and neighbourhood. Every row also names who is advertising, so an export splits agency stock from private owners after the fact. Switch on full details and each row additionally carries map coordinates, the energy certificate, build year, bathroom count, condition, fitted features, the complete photo set, floor plans, the full advert text and the advertiser's phone number.

**Use something else when:** the property is not in Portugal, or is on Idealista rather than Imovirtual. Use [Idealista Scraper](https://apify.com/sian.agency/smart-idealista-scraper?fpr=sian) for Idealista in both Portugal and Spain, with the same sale-and-rent row shape. Use [Otodom Scraper](https://apify.com/sian.agency/otodom-property-scraper?fpr=sian) for Poland, on the same portal platform Imovirtual runs on. Use [Fotocasa Scraper](https://apify.com/sian.agency/fotocasa-property-scraper?fpr=sian) for Spain, for cross-border price comparison against the Portuguese market. This actor covers what Imovirtual publishes on its own portal: apartments, houses, land, commercial premises, warehouses, garages, rooms and new developments, each for sale or to rent, plus the estate-agency pages behind those adverts. It reads what the portal serves a visitor. Sold prices are not published by Imovirtual at all, and the portal's mortgage simulator, valuation module and editorial pages are not part of it.

### 🤖 Use with AI agents

Already connected to the [Apify MCP server](https://mcp.apify.com)? Just ask for this Actor by name: sian.agency/imovirtual-property-scraper

**Your agent can pay for its own runs.** This Actor is eligible for [agentic payments](https://docs.apify.com/platform/actors/publishing/monetize), so an agent can discover it, run it and settle the bill over [x402](https://www.x402.org/) (USDC on Base) or [Skyfire](https://www.skyfire.xyz/) — without an Apify account or API token of its own. Billing is the same either way: per successful row, never for errors.

Otherwise copy this prompt into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```text
I want property listings, asking prices and agent contacts from Imovirtual.com using the Apify Actor `sian.agency/imovirtual-property-scraper`.

Use it when I need: Portuguese sale and rental adverts as rows: asking price or monthly rent in euros, price per square metre, floor and plot area, the T0-T4+ typology Portuguese buyers actually search, floor, and location down to district, council, parish and neighbourhood. Every row also names who is advertising, so an export splits agency stock from private owners after the fact. Switch on full details and each row additionally carries map coordinates, the energy certificate, build year, bathroom count, condition, fitted features, the complete photo set, floor plans, the full advert text and the advertiser's phone number.

Don't use it when: the property is not in Portugal, or is on Idealista rather than Imovirtual — use smart-idealista-scraper or otodom-property-scraper or fotocasa-property-scraper instead.

How to call it: set `transaction` to `comprar` for sale or `arrendar` to rent, pick a `propertyType` (`apartamento`, `moradia`, `terreno`, `imoveis-comerciais`, `armazens`, `garagem`, `quarto` or `empreendimento`) and give `locations` a list of Imovirtual's own areas — the 18 mainland districts such as `lisboa`, `porto` and `faro`, the 11 Atlantic islands such as `ilha-da-madeira`, or `todo-o-pais` for the whole country. Narrow with `priceMin`, `priceMax`, `areaMin`, `areaMax`, `buildYearMin`, `typology` (T0 to T4+), `market` (new build or resale), `ownerType` (private owners or agencies) and `listedWithinDays`; every one of those goes to Imovirtual's own filter, so anything excluded is never saved and never billed. `sortBy` decides which listings you get when `maxResults` bites before the result set runs out. `fullDetails` opens each advert for its coordinates, certificate, features, photo set and phone, for an extra charge per listing. To expand adverts you already have, set `operation` to `detail` and pass `listingUrls`; for the firm behind a listing, set `operation` to `agency` and pass `agencyUrls`; to reach a parish or a map area the picker does not list, paste its Imovirtual address into `searchUrls`.

Start with this input:
{
  "operation": "search",
  "transaction": "comprar",
  "propertyType": "apartamento",
  "locations": [
    "lisboa"
  ],
  "typology": [
    "T2",
    "T3"
  ],
  "priceMax": 400000,
  "fullDetails": true,
  "maxResults": 100
}

Ask me which part of Portugal to cover, whether they want listings for sale or to rent, and whether the coordinates, energy certificate, full advert text and advertiser phone are worth the extra per-listing charge, then run the Actor and summarise the results as a table.
```

**Things you can ask your agent for:**

- *Find T2 apartments for sale in Porto under EUR 300,000 and keep only the ones with an A or B energy certificate.*
- *Pull every Lisbon apartment listed by a private owner in the last week, with the advert text and a phone number.*
- *Compare median price per square metre for T3 apartments across Lisboa, Porto and Faro.*

Machine-readable API, MCP config and OpenAPI definition for this Actor are published at [apify.com/sian.agency/imovirtual-property-scraper.md](https://apify.com/sian.agency/imovirtual-property-scraper.md).

### 📋 Overview

**Imovirtual is where Portugal looks for a home** — 1.5 million visits a month, and the Consumer's Choice winner in its category twelve years running. This Actor reads it the way a research team needs it read.

**What you get here that a search-card dump does not have:**

- ✅ **Map coordinates on every expanded row**: latitude and longitude, so listings drop straight onto a map or into a spatial join
- ⚡ **The energy certificate**: mandatory on every Portuguese sale, and the fastest read on how much work a property needs
- 🎯 **The advertiser's phone number**: the agency switchboard and the named agent, exactly as published on the advert
- 💰 **Mid-market pricing**: $2.50 per 1,000 listings, with a deeper row than anything at that price
- 💎 **The agency record**: registered address, postal code, switchboard, website, live portfolio split and areas covered
- ✨ **Filters that are actually honest**: every filter was measured against Imovirtual's own result count and against the rows it returns, and the ones the site does not respect were left out on purpose

***

### ✨ Features

- 🔍 **Three modes in one Actor**: property search, full property detail, and estate-agency profile
- 🇵🇹 **Full national coverage**: 18 mainland districts, all 11 Atlantic islands, or the whole country in one run
- 🏘️ **Every property section**: apartments, houses, land, commercial premises, warehouses, garages, rooms and new developments
- 🤝 **Sale and rental**: both sides of the market, with the money field read correctly on each
- 🛏️ **Portuguese typology, translated**: pick T0 to T4+ the way a buyer would, and the Actor handles the off-by-one in the source data
- 🔬 **One switch for depth**: `fullDetails` expands every search result into a complete record
- 📄 **The full advert text**: two thousand characters of description, not a truncated preview
- 🖼️ **The complete photo set**: every image the advertiser uploaded, plus floor plans and any video
- 🔖 **The advertiser's own reference**: the code an agency's CRM stamps on a property, which is what makes cross-portal deduplication work
- 📊 **Run report included**: what came back, what did not, and what it cost

***

### 🎬 Quick Start

Pick a deal type, a property type and an area. Press Start. Rows land in your dataset within a minute.

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~imovirtual-property-scraper/runs?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"operation":"search","transaction":"comprar","propertyType":"apartamento","locations":["lisboa"],"maxResults":100}'
```

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose what to search

Sale or rental, which property type, and which districts or islands. The defaults are Lisbon apartments for sale, so a bare run works.

#### Step 2: Narrow it, or do not

Price, area, typology, new build against resale, private owners only, build year, how recently it was listed. Each filter is applied by Imovirtual itself, so a narrower run reads fewer pages and costs less.

#### Step 3: Decide how deep to go

Leave `fullDetails` off for a fast price-and-area sweep. Turn it on when you need coordinates, the certificate, the features and a phone number.

**That's it! In about a minute, you'll have:**

- A flat table of Portuguese listings with prices, areas and locations
- Export-ready JSON, CSV or Excel
- A run report showing exactly what came back and what it cost

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `operation` | string | No | `search`, `detail` or `agency`. Defaults to `search` |
| `transaction` | string | No | `comprar` (for sale) or `arrendar` (to rent) |
| `propertyType` | string | No | `apartamento`, `moradia`, `terreno`, `imoveis-comerciais`, `armazens`, `garagem`, `quarto`, `empreendimento` |
| `locations` | array | No | Imovirtual's own areas — `lisboa`, `porto`, `faro`, `ilha-da-madeira` … or `todo-o-pais` |
| `searchUrls` | array | No | Paste result-page addresses to read them exactly as given |
| `listingUrls` | array | No | Advert addresses for the `detail` operation |
| `agencyUrls` | array | No | Agency addresses for the `agency` operation |
| `fullDetails` | boolean | No | Expand every search result into a complete record |
| `maxResults` | integer | No | How many listings to keep per area. Default 100 |
| `priceMin` / `priceMax` | integer | No | Price or monthly rent bounds, in euros |
| `areaMin` / `areaMax` | integer | No | Floor area bounds, in m² |
| `typology` | array | No | `T0`, `T1`, `T2`, `T3`, `T4+` |
| `market` | string | No | `any`, `primary` (new build) or `secondary` (resale) |
| `ownerType` | string | No | `any`, `private` or `agency` |
| `buildYearMin` | integer | No | Four-digit year, oldest acceptable build year |
| `listedWithinDays` | string | No | `any`, `1`, `3`, `7`, `14`, `30`, `60` |
| `sortBy` | string | No | `default`, `priceAsc`, `priceDesc`, `newest` |

**Example — Lisbon T2 and T3 apartments under €400,000, fully expanded:**

```json
{
  "operation": "search",
  "transaction": "comprar",
  "propertyType": "apartamento",
  "locations": ["lisboa"],
  "typology": ["T2", "T3"],
  "priceMax": 400000,
  "fullDetails": true,
  "maxResults": 100
}
```

**Example — expand specific adverts:**

```json
{
  "operation": "detail",
  "listingUrls": [
    { "url": "https://www.imovirtual.com/pt/anuncio/apartamento-t3-para-venda-ID1iQXv" }
  ]
}
```

**Example — profile an estate agency:**

```json
{
  "operation": "agency",
  "agencyUrls": [
    { "url": "https://www.imovirtual.com/pt/empresas/agencias-imobiliarias/remax-grupo-team-ID4062704" }
  ]
}
```

***

### 📤 Output

Results are saved to the Apify dataset with **50+ fields**. The Output tab carries one view per operation, so nothing renders as an empty column.

| Field | Type | Description |
|-------|------|-------------|
| `titleText` | string | The advert headline |
| `url` | string | The listing address on Imovirtual |
| `price` | number | Asking price on a sale, monthly rent on a rental |
| `pricePerSqm` | number | Price per square metre, as Imovirtual computes it |
| `areaSqm` | number | Floor area in m² |
| `plotAreaSqm` | number | Plot area, on houses (a plot listing puts its size in `areaSqm`) |
| `typology` | string | `T0` … `T4+` |
| `district` / `council` / `parish` / `neighbourhood` | string | Four levels of location |
| `latitude` / `longitude` | number | Map coordinates *(expanded rows)* |
| `energyCertificate` | string | `A+` … `F`, or `EXEMPT` *(expanded rows)* |
| `buildYear` | integer | Year built *(expanded rows)* |
| `bathrooms` | integer | Bathroom count *(expanded rows)* |
| `extras` / `equipment` | array | Lift, garage, terrace, balcony, fitted appliances *(expanded rows)* |
| `contactPhone` / `agencyPhone` | string | The numbers the advertiser publishes *(expanded rows)* |
| `descriptionText` | string | The full advert text *(expanded rows)* |
| `imageUrls` / `floorPlanUrls` | array | Every photo and floor plan *(expanded rows)* |
| `referenceId` | string | The advertiser's own CRM reference *(expanded rows)* |
| `agencyName` / `agencyUrl` | string | The estate agency behind the listing |
| `activeAds` / `saleAds` / `rentAds` | integer | Portfolio size *(agency rows)* |

**Example row (expanded):**

```json
{
  "operation": "search",
  "listingId": 19269818,
  "titleText": "Apartamento T3 para venda",
  "url": "https://www.imovirtual.com/pt/anuncio/apartamento-t3-para-venda-ID1iQXv",
  "transaction": "sale",
  "propertyType": "Apartment",
  "price": 1600000,
  "currency": "EUR",
  "pricePerSqm": 8695.65,
  "areaSqm": 184,
  "typology": "T3",
  "rooms": 4,
  "floor": "Third",
  "district": "Lisboa",
  "council": "Oeiras",
  "parish": "Oeiras e S. Julião da Barra, Paço de Arcos e Caxias",
  "latitude": 38.699932,
  "longitude": -9.295546,
  "energyCertificate": "A",
  "buildYear": 2020,
  "bathrooms": 3,
  "buildingType": "Block",
  "constructionStatus": "Ready to use",
  "extras": ["Lift", "Garage"],
  "advertiserType": "agency",
  "agencyName": "Remax Grupo Team",
  "agencyPhone": "+351214152440",
  "contactName": "Collection Team",
  "contactPhone": "+351923232045",
  "referenceId": "126801067-113",
  "mediaCount": 45,
  "listedAt": "2026-09-08T19:10:10Z"
}
```

***

### 💼 Use Cases & Examples

#### 1. Portugal price index and valuation models

**Analysts building a hedonic model need attributes, not headlines.**

**Input:** one district, weekly, `fullDetails: true`
**Output:** price, price per m², area, typology, build year, energy certificate and exact coordinates on every row
**Use:** a panel that supports a real regression instead of a scatter plot of asking prices

#### 2. Direct-to-owner acquisition

**Buyer's agents and investors want the stock with no agent in the middle.**

**Input:** `ownerType: "private"`, `listedWithinDays: "7"`
**Output:** the roughly 1% of listings placed by owners — 153 of 16,474 Lisbon apartments on the day this was measured
**Use:** a short, high-intent outreach list refreshed every week

#### 3. Estate-agency lead lists

**Anyone selling software, photography or portal services to Portuguese agencies.**

**Input:** `operation: "agency"` with agency links harvested from a search run
**Output:** registered address, postal code, switchboard, website, live portfolio split between sale and rental, areas covered, years on the portal
**Use:** a qualified prospect record with the firm's size already attached

#### 4. New-listing alerts on a schedule

**Relocation consultants and buying agents who need to be first.**

**Input:** `listedWithinDays: "1"`, run daily on a schedule
**Output:** only what appeared since yesterday
**Use:** a watchlist that stays small and never repeats itself

#### 5. Cross-portal deduplication

**Aggregators reconciling the same home across three sites.**

**Input:** `fullDetails: true`
**Output:** `referenceId`, the code the agency's own CRM stamps on the property
**Use:** three duplicate records collapse to one, and the count you report is the count that exists

#### 6. Golden-visa and relocation research

**Advisers comparing what a budget actually buys across the country.**

**Input:** `locations: ["todo-o-pais"]` or the Algarve and Madeira alone
**Output:** every district and island with energy certificate and build year attached
**Use:** a like-for-like comparison across 29 areas instead of the three everyone writes about

#### 7. Rental market monitoring

**Councils, researchers and build-to-rent operators tracking asking rents.**

**Input:** `transaction: "arrendar"`, monthly, one district per run
**Output:** monthly rents with area, typology and parish
**Use:** a rent index at parish resolution rather than city averages

***

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/imovirtual-property-scraper').call({
  operation: 'search',
  transaction: 'comprar',
  propertyType: 'apartamento',
  locations: ['lisboa'],
  typology: ['T2', 'T3'],
  priceMax: 400000,
  fullDetails: true,
  maxResults: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/imovirtual-property-scraper').call(run_input={
    'operation': 'search',
    'transaction': 'arrendar',
    'propertyType': 'apartamento',
    'locations': ['porto'],
    'priceMax': 1200,
    'maxResults': 200,
})

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item['titleText'], item['price'], item['parish'])
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~imovirtual-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"operation":"agency","agencyUrls":[{"url":"https://www.imovirtual.com/pt/empresas/agencias-imobiliarias/remax-grupo-team-ID4062704"}]}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: a daily schedule
2. **HTTP Request**: run the Actor with `listedWithinDays: "1"`
3. **Process**: filter the returned rows on your own criteria
4. **Action**: append to a sheet, write to a database, or send the shortlist to Slack

***

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **25 rows** per run — every field, every operation, same quality
- No credit card required
- Enough to see the data shape before you commit

#### PAID Tier (Production Ready)

- **Unlimited** rows per run
- Pay per successful row. A search that matched nothing, an advert Imovirtual has withdrawn, and any link that could not be read all cost nothing
- One result page returns up to 70 listings, so a broad sweep is cheap

💰 **$2.50 per 1,000 listings** — mid-market for Imovirtual on the Apify Store, with coordinates, certificate, phone and full advert text that the others do not return.

🔗 [View current pricing](https://apify.com/sian.agency/imovirtual-property-scraper?fpr=sian)

***

### ❓ Frequently Asked Questions

**Q: Does this cover rentals as well as sales?**
A: Yes, and both were tested separately. Imovirtual serves them from different result pages, and on a rental the price column carries the monthly rent.

**Q: What does `fullDetails` actually add?**
A: Map coordinates, energy certificate, build year, bathroom count, condition, building type, fitted features and equipment, the advertiser's phone number, the complete photo set, floor plans, any video, and the full advert text. It is one extra page read per listing, billed as a Property Detail on top of the listing.

**Q: Can I search a specific parish or neighbourhood?**
A: Yes. Build the search on Imovirtual, copy the address from your browser bar and paste it into Search URLs. It is read exactly as given.

**Q: Why is there no balcony, pool or air-conditioning filter?**
A: Because they do not work. Imovirtual accepts them and the result count moves, but the rows it returns do not honour them — a garage-filtered page returned an advert whose own listing shows no garage. Those features still come back on every expanded row, so filter them yourself and the answer will be right.

**Q: What is T0, T1, T2?**
A: Portugal's bedroom typology. T0 is a studio, T1 has one bedroom, and so on. Imovirtual stores a room count that runs one ahead of the T number. This Actor converts it and puts both values on every row.

**Q: Do I need a proxy or a login?**
A: No. Every page it reads is public, and nothing here needs an account, a key or a browser.

**Q: How many listings can I get?**
A: `maxResults` applies per area, and you can pass several areas in one run. Imovirtual itself publishes tens of thousands per section — 73,940 apartments for sale nationwide when this was written.

**Q: What output formats are available?**
A: JSON, CSV, Excel and XML, straight from the Apify dataset or over the API.

***

### 🐛 Troubleshooting

**A run returns no rows**

- The combination may genuinely have no matches. Rooms are rental-only and new developments are sale-only, and the run stops at validation on those.
- Clear a filter or two and widen the area. The run log prints Imovirtual's own result count before it reads anything.

**An area is rejected**

- Use one of Imovirtual's own 29 areas. The islands are named individually (`ilha-da-madeira`, `ilha-de-sao-miguel`), never by archipelago.

**A pasted URL is skipped**

- Search URLs must be `/pt/resultados/…` addresses, advert URLs `/pt/anuncio/…`, agency URLs `/pt/empresas/…`. Copy them from the browser bar rather than retyping.

**Fewer rows than `maxResults`**

- Imovirtual ran out of matches, or the FREE tier row cap stopped the run at 25. The run log says which.

***

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

Imovirtual is a trademark of Grupa OLX sp. z o.o. This Actor is not affiliated with, endorsed by, or sponsored by Imovirtual or Grupa OLX.

***

### 🤝 Support

**Join our active support community**

- For issues or questions, open an issue in the actor's repository
- Check [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

## `operation` (type: `string`):

Pick one per run. Property Search walks Imovirtual's own result pages for any district or island and returns up to 70 listings a page, sale and rental alike. Switch on Full property details and each listing is expanded with its map coordinates, energy certificate, build year and the advertiser's phone number. Property Detail does the same for advert links you paste in. Agency Profile returns the firm itself: address, phone, website, portfolio size and the districts it lists in.

## `transaction` (type: `string`):

Which side of the market to read. Imovirtual keeps sale and rental adverts in separate result pages, so a run returns one or the other. On a rental the money field carries the monthly rent in euros; on a sale it carries the asking price. Ignored when you paste your own Search URLs — those are read exactly as given.

## `propertyType` (type: `string`):

Which section of Imovirtual to read. Rooms exist only as rentals and new developments only as sales, so pairing either with the other deal type returns nothing — the run stops at validation and nothing is charged. Counts above are Imovirtual's own nationwide totals for sale, measured 2026-09-08.

## `locations` (type: `array`):

Which parts of Portugal to read. Every value is one of Imovirtual's own 29 top-level areas — the 18 mainland districts plus the 11 Atlantic islands — or `todo-o-pais` for the whole country in a single run. Areas are read one after another and the result cap applies per area. A council, parish or neighbourhood is narrower than the site indexes at this level: paste that page's Imovirtual address into Search URLs instead.

## `searchUrls` (type: `array`):

Paste Imovirtual result-page addresses to read them exactly as given — the fastest way to reproduce a search you already built on the site, including councils, parishes, neighbourhoods and map areas that are narrower than the district list above. When this is filled the deal type, property type, districts and every filter below are ignored, because the address already carries them.

## `listingUrls` (type: `array`):

Imovirtual advert addresses to expand, one row each, for the Property Detail operation. Every link looks like https://www.imovirtual.com/pt/anuncio/{slug}-ID{code} — copy it straight from the browser bar. A link the site no longer serves is reported as not found and is not charged.

## `agencyUrls` (type: `array`):

Imovirtual estate-agency addresses to profile, one row each, for the Agency Profile operation. Every link looks like https://www.imovirtual.com/pt/empresas/agencias-imobiliarias/{slug}-ID{id} — the link behind the agency name on any advert.

## `fullDetails` (type: `boolean`):

Open every listing a search returns and add what the result card does not carry. That is map coordinates, the energy certificate, build year, bathroom count, condition, building type, fitted features, the advertiser's phone number, the complete photo set, floor plans and the full advert text. Each expanded listing is one extra page read and is billed as a Property Detail on top of the listing. Leave it off for a fast price-and-area sweep.

## `maxResults` (type: `integer`):

How many listings to keep for each district, island or search URL before moving to the next one. Imovirtual serves up to 70 listings per page read, so 100 costs two reads. Free-plan runs are capped lower regardless of what you set here.

## `priceMin` (type: `integer`):

Only keep listings at or above this price in euros — the asking price on a sale, the monthly rent on a rental. Leave at 0 for no minimum. Applied by Imovirtual itself, so a narrowed run reads fewer pages and costs less.

## `priceMax` (type: `integer`):

Only keep listings at or below this price in euros. Leave at 0 for no maximum.

## `areaMin` (type: `integer`):

Only keep listings of at least this floor area in square metres. Leave at 0 for no minimum. On land this is the plot size.

## `areaMax` (type: `integer`):

Only keep listings of at most this floor area in square metres. Leave at 0 for no maximum.

## `typology` (type: `array`):

Portuguese bedroom typology, the way Portuguese buyers search: T0 is a studio, T1 has one bedroom, T4+ has four or more. Pick as many as you want; leave empty for every typology. Imovirtual stores this as a room count that runs one ahead of the T number, and this actor does the conversion for you — each row carries both the typology and the raw room count.

## `market` (type: `string`):

Whether to keep newly built property, resale property, or both. Imovirtual's own split for Lisbon apartments on 2026-09-08 was 4,661 new build against 11,812 resale.

## `ownerType` (type: `string`):

Whether to keep adverts placed by private owners, by estate agencies, or both. Private owners are rare on Imovirtual — 153 of 16,474 Lisbon apartments for sale on 2026-09-08 — which is exactly why they are worth isolating for direct-approach outreach.

## `buildYearMin` (type: `integer`):

Only keep property built in this year or later, as a four-digit year. Leave at 0 for any age. Useful for screening out stock that will need work: 4,240 of 16,474 Lisbon apartments for sale were built in 2015 or later.

## `listedWithinDays` (type: `string`):

Only keep adverts first published within this window — the setting to use on a daily schedule so each run returns what is genuinely new. Lisbon apartments for sale published in the last 24 hours numbered 198 on 2026-09-08, against 16,474 in total.

## `sortBy` (type: `string`):

The order Imovirtual returns listings in, which decides which ones you get when the result cap bites before the result set runs out. Cheapest-first paired with a low cap is how you pull the bottom of a market rather than a random slice of it.

## Actor input object example

```json
{
  "operation": "search",
  "transaction": "comprar",
  "propertyType": "apartamento",
  "locations": [
    "lisboa"
  ],
  "searchUrls": [],
  "listingUrls": [],
  "agencyUrls": [],
  "fullDetails": false,
  "maxResults": 100,
  "priceMin": 0,
  "priceMax": 0,
  "areaMin": 0,
  "areaMax": 0,
  "typology": [],
  "market": "any",
  "ownerType": "any",
  "buildYearMin": 0,
  "listedWithinDays": "any",
  "sortBy": "default"
}
```

# Actor output Schema

## `imovirtualListings` (type: `string`):

Every listing a Property Search returned — price, area, typology, location and advertiser.

## `imovirtualFullDetails` (type: `string`):

Listings expanded with map coordinates, energy certificate, build year, features, the advertiser’s phone number and the full advert text.

## `imovirtualAgencies` (type: `string`):

Agency profiles — address, phone, website, live portfolio split and areas covered.

## `scrapingSummary` (type: `string`):

HTML summary showing successful and failed results with key metrics

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "operation": "search",
    "transaction": "comprar",
    "propertyType": "apartamento",
    "locations": [
        "lisboa"
    ],
    "searchUrls": [],
    "listingUrls": [],
    "agencyUrls": [],
    "fullDetails": false,
    "maxResults": 100,
    "priceMin": 0,
    "priceMax": 0,
    "areaMin": 0,
    "areaMax": 0,
    "typology": [],
    "market": "any",
    "ownerType": "any",
    "buildYearMin": 0,
    "listedWithinDays": "any",
    "sortBy": "default"
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/imovirtual-property-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "operation": "search",
    "transaction": "comprar",
    "propertyType": "apartamento",
    "locations": ["lisboa"],
    "searchUrls": [],
    "listingUrls": [],
    "agencyUrls": [],
    "fullDetails": False,
    "maxResults": 100,
    "priceMin": 0,
    "priceMax": 0,
    "areaMin": 0,
    "areaMax": 0,
    "typology": [],
    "market": "any",
    "ownerType": "any",
    "buildYearMin": 0,
    "listedWithinDays": "any",
    "sortBy": "default",
}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/imovirtual-property-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "operation": "search",
  "transaction": "comprar",
  "propertyType": "apartamento",
  "locations": [
    "lisboa"
  ],
  "searchUrls": [],
  "listingUrls": [],
  "agencyUrls": [],
  "fullDetails": false,
  "maxResults": 100,
  "priceMin": 0,
  "priceMax": 0,
  "areaMin": 0,
  "areaMax": 0,
  "typology": [],
  "market": "any",
  "ownerType": "any",
  "buildYearMin": 0,
  "listedWithinDays": "any",
  "sortBy": "default"
}' |
apify call sian.agency/imovirtual-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sian.agency/imovirtual-property-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ubPXHhPg9YcSOegMl/builds/rd80obUjtEkdZg7hg/openapi.json
