# Imovirtual Scraper (`solidcode/imovirtual-scraper`) Actor

\[💰 $2.50 / 1K] Extract property listings from Imovirtual, Portugal's leading real-estate portal. Search by location, buy/rent, property type, price, area and rooms — or paste search URLs — to get prices, areas, locations, photos and agency contacts.

- **URL**: https://apify.com/solidcode/imovirtual-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Real estate, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 23 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 results

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Imovirtual Scraper

Pull property listings from Imovirtual — Portugal's leading real-estate portal — at scale: prices in euros, living area in m², T0–T5+ bedroom counts, full photo galleries, agency details, city and district, and new-development flags for every for-sale and for-rent listing across the country. Built for Portugal property investors, estate agents, relocation services, and proptech analysts who need a clean, structured Imovirtual dataset without hand-copying listings from the portal one page at a time.

### Why This Scraper?

- **Two ways to search — no URL building required** — fill in a guided builder (location, buy/rent, type, price, area, bedrooms) or paste Imovirtual search URLs straight from your browser. Most competing tools accept URLs only.
- **Every Portuguese place name resolves** — all 18 districts, 11 island regions and 308 councils, plus regions ("Algarve", "Alentejo"), English names ("Lisbon") and resort towns ("Vilamoura", "Estoril"). Multi-district regions are pulled in a single pass, and a name we can't place stops the run with a plain explanation instead of handing you an empty file.
- **Nine property categories** — apartments, houses, land, commercial spaces, garages, rooms, warehouses, new developments, or "any type" — each mapped to Imovirtual's own Portuguese categories (Apartamento, Moradia, Terreno, Empreendimento…).
- **Buy and rent in one actor** — flip a single dropdown between Comprar (for sale) and Arrendar (for rent); rent rows carry the monthly euro price in the same field.
- **Server-side price, area, and bedroom filters** — set min/max price (€), min/max living area (m²), and multi-select T0–T5+ bedroom counts; filters run on Imovirtual itself, so you only collect — and only pay for — listings that match.
- **Room counts that admit what they don't know** — Imovirtual buckets everything above nine rooms into a single open "10 or more", with no exact figure behind it. Those rows are marked `roomsAreMinimum: true` and labelled `"9+"` instead of being rounded into a precise-looking 9, so a 14-unit building never lands in your dataset posing as a 9-bedroom home.
- **Thousands of listings per search, each one billed once** — pagination walks every results page, and the sponsored copy Imovirtual re-displays at the foot of every page is matched back to its original and dropped. You are never charged twice for the same property.
- **One flat row per listing, with its fill rate published** — title, total price, price per m², living area, bedrooms, total rooms, city, region, agency, photo URLs and three separate dates. Every output table below states how often each field actually arrives, and empty keys are dropped rather than padded with blanks — so a missing floor number means the seller never published one, not that we lost it.
- **Agency vs. private-owner intelligence** — every row flags whether it came from an agency (with agency name and type) or a private seller, plus promoted and exclusive-offer markers.
- **New-development detection** — empreendimento (new-construction) projects are flagged with `isDevelopment` and a development name, so you can separate off-plan inventory from resale stock.
- **Three separate dates, each one honest** — `dateCreated` is the day the listing first went live, `lastRefreshedAt` is the last re-activation, and `pushedUpAt` is the last paid bump. A 15-month-old ad re-bumped this morning shows all three, so "newest listing" means what you think it means.
- **Clean, analysis-ready output** — euro prices as numbers, ISO-8601 UTC timestamps, null fields stripped, and consistent camelCase field names.

### Use Cases

**Real-Estate Investment & Acquisition**

- Compare asking prices and price-per-m² across Lisboa, Porto, and the Algarve
- Surface new-development (empreendimento) projects for off-plan opportunities
- Benchmark sale vs. rent yields by collecting both transaction types for one area
- Size up building plots by area, with a minimum-m² filter applied at the source

**Lead Generation for Agents**

- Build prospect lists of private-owner listings ripe for an agency mandate
- Map competing agencies by name and type across a target district
- Monitor exclusive and promoted listings to gauge competitor activity
- Feed fresh listing inventory straight into your CRM

**Market & Price Analysis**

- Track median price-per-m² movements by city and property type over time
- Measure inventory volume by district, bedroom count, or price band
- Compare apartment vs. house vs. land pricing across Portuguese regions
- Build price-band histograms from min/max-filtered searches

**Relocation & Property Services**

- Assemble shortlists filtered by location, budget, and T-typology bedroom count
- Generate area-by-area rental availability reports for incoming clients
- Pull listing photos, city and district for relocation briefing packs

**Proptech & Data Products**

- Power a Portuguese property portal, valuation model, or comparison tool
- Refresh an existing listings database with current prices and bump dates
- Build alerting on new listings within a price and area window

### Getting Started

#### Search by Location

The simplest run — just name a district, council or region:

```json
{
    "location": "Lisboa",
    "maxResults": 100
}
```

#### Filtered Buy Search

Apartments for sale in Porto, priced €200k–€350k, with one or two bedrooms (T1 or T2):

```json
{
    "transaction": "buy",
    "propertyType": "apartment",
    "location": "Porto",
    "priceMin": 200000,
    "priceMax": 350000,
    "rooms": ["1", "2"],
    "maxResults": 300
}
```

#### Rent Search with a Price Band

Properties to rent in Lisboa up to €1,500/month:

```json
{
    "transaction": "rent",
    "propertyType": "apartment",
    "location": "Lisboa",
    "priceMax": 1500,
    "areaMin": 60,
    "maxResults": 200
}
```

#### Paste Imovirtual Search URLs

Already filtered on the site? Copy the URL from your browser — its baked-in filters are used exactly as-is, and the guided fields are ignored:

```json
{
    "startUrls": [
        "https://www.imovirtual.com/pt/resultados/comprar/moradia/faro",
        "https://www.imovirtual.com/pt/resultados/arrendar/apartamento/lisboa"
    ],
    "maxResults": 500
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `startUrls` | string\[] | `[]` | Paste one or more Imovirtual search-results URLs. The fastest way to get exactly what you see on the site. When provided, the guided "Build a Search" fields below are ignored. Up to 50 URLs. |

#### Build a Search

Used only when no `startUrls` are provided.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `transaction` | select | `buy` | For Sale (Comprar) or For Rent (Arrendar). |
| `location` | string | `Lisboa` | District ("Lisboa", "Porto", "Faro"), council ("Cascais", or "Lisboa/Cascais" to disambiguate), region ("Algarve", "Alentejo", "Madeira", "Açores"), or "Portugal" for nationwide. Accents and English names accepted. An unrecognised place stops the run with an explanation rather than returning nothing. |
| `propertyType` | select | `apartment` | Apartment, House, Land, Commercial space, Garage, Room, Warehouse, New development, or Any type. |

#### Filters

Applied to the Imovirtual search itself, so you only collect matching listings.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `priceMin` | integer | null | Minimum price in € — monthly rent when renting, total price when buying. |
| `priceMax` | integer | null | Maximum price in €. |
| `areaMin` | integer | null | Minimum living area in m². |
| `areaMax` | integer | null | Maximum living area in m². |
| `rooms` | string\[] | `[]` | Bedroom counts in Portuguese T-typology — T0 (studio) through T5+. `"3"` means T3, i.e. 3 bedrooms, and comes back as `bedrooms: 3` on every row. Multi-select; combined with OR. |

#### Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Maximum listings per search or URL. Results come in full pages, so the last page may overshoot by a few rows. Set to `0` for no cap (an internal safety limit of 50,000 then applies). |

### Output

Each listing becomes one flat row. Here is a real result, collected from a Lisboa apartment search (image tokens shortened for readability):

```json
{
    "id": "19165860",
    "title": "Apartamento T2 Remodelado por Arquiteto | Vista Rio Tejo | Avenida",
    "url": "https://www.imovirtual.com/pt/ad/apartamento-t2-remodelado-por-arquiteto-vista-rio-tejo-avenida-ID1ipUM",
    "slug": "apartamento-t2-remodelado-por-arquiteto-vista-rio-tejo-avenida-ID1ipUM",
    "transaction": "buy",
    "propertyType": "apartment",
    "estate": "FLAT",
    "totalPrice": 675000,
    "currency": "EUR",
    "pricePerSqm": 5869.57,
    "area": 115,
    "bedrooms": 2,
    "bedroomsLabel": "2",
    "totalRooms": 3,
    "roomsAreMinimum": false,
    "floor": 2,
    "address": "Corredor da Torrinha",
    "city": "Estrela",
    "region": "Lisboa",
    "images": [
        "https://ireland.apollo.olxcdn.com/v1/files/eyJmbiI6ImMya2Z5bm9i.../image;s=1280x1024;q=80",
        "https://ireland.apollo.olxcdn.com/v1/files/eyJmbiI6InpqcW9pamRo.../image;s=1280x1024;q=80"
    ],
    "agencyName": "Group HBC",
    "agencyType": "AGENCY",
    "isPrivateOwner": false,
    "isPromoted": false,
    "isExclusive": false,
    "isDevelopment": false,
    "shortDescription": "Descubra este magnifico apartamento T2, totalmente remodelado e cuidadosamente projetado pelo Arquiteto Ricardo Rosa...",
    "dateCreated": "2026-05-29T14:12:58Z",
    "lastRefreshedAt": "2026-08-27T14:35:27Z",
    "pushedUpAt": "2026-08-27T14:35:28Z",
    "searchQuery": "buy/apartment/Lisboa",
    "scrapedAt": "2026-08-27T15:41:05Z"
}
```

This row shows the three dates doing their job: the ad first went live on 29 May and was re-listed and bumped on 27 August. It also shows the bedroom mapping — the title says T2, so `bedrooms` is `2` and `totalRooms` is `3` (Imovirtual counts the living room too), and `roomsAreMinimum` is `false` because that count is exact. Imovirtual files its largest properties under a single open bracket, "10 rooms or more", and publishes no figure beyond it. Those listings come back with `roomsAreMinimum: true` and a `bedroomsLabel` of `"9+"`, so a whole building never poses as a precise 9-bedroom home. They are about 1% of a typical mixed run and 4% of a big-city apartment search.

**About the availability column.** Imovirtual publishes some details only for the property types that have them, and some only when the seller filled them in. The tables below give the share of rows carrying each field, measured over a 2,557-listing audit across eight different searches (apartments, houses, land, and rooms, for sale and to rent). Fields that are empty are removed from the row entirely.

#### Core Fields

| Field | Type | Availability | Description |
|-------|------|--------------|-------------|
| `id` | string | 100% | Imovirtual listing identifier |
| `title` | string | 100% | Listing title |
| `url` | string | 100% | Canonical listing URL (`/pt/ad/<slug>-ID<token>`) |
| `slug` | string | 100% | URL slug, ending in the ad's public token |
| `transaction` | string | 100% | `buy` or `rent` |
| `propertyType` | string | 100% | Normalized type: apartment, house, land, commercial, garage, room, warehouse, development |
| `estate` | string | 100% | Imovirtual's raw estate category (e.g. `FLAT`, `HOUSE`, `TERRAIN`, `ROOM`) |
| `shortDescription` | string | 100% | Short listing description |

#### Price & Specs

| Field | Type | Availability | Description |
|-------|------|--------------|-------------|
| `totalPrice` | number | 98% | Total price in € — sale price, or monthly rent for rent listings. Absent on "price on request" ads |
| `currency` | string | 98% | Price currency (EUR) — present whenever `totalPrice` is |
| `pricePerSqm` | number | 98% | Price per m² in € |
| `area` | number | 99.7% | Living area in m². For land listings this is the plot size |
| `terrainArea` | number | **houses 77–86%, otherwise absent** | Plot / terrain area in m². Imovirtual publishes it for houses and villas; apartments, land and rooms don't carry it |
| `bedrooms` | number | **99% on flats & houses, absent on land and rooms** | Bedrooms — the Portuguese T-number (a T3 gives `3`). Matches the `rooms` values you filtered on. `0` for a studio. Land and room listings have no T-typology |
| `bedroomsLabel` | string | same as `bedrooms` | The bedroom count as Imovirtual states it: `"3"` when the figure is exact, `"9+"` when the listing sits in Imovirtual's open "10 rooms or more" bracket. The column to read when you want the count at a glance |
| `totalRooms` | number | same as `bedrooms` | Imovirtual's own room count, which includes the living room and is one higher than `bedrooms` (a T3 gives `4`) |
| `roomsAreMinimum` | boolean | same as `bedrooms` | `true` on the ~1% of listings (4% of big-city apartment searches) that Imovirtual files under "10 rooms or more" — mostly whole buildings and investment lots. On those rows `bedrooms` and `totalRooms` are floors, not exact counts. `false` everywhere else |
| `floor` | number/string | **apartments 63–70%, otherwise absent** | Floor (number, or `cellar` / `attic`). Imovirtual only publishes a floor for flats, and only when the seller entered one |

#### Location & Media

| Field | Type | Availability | Description |
|-------|------|--------------|-------------|
| `address` | string | **~47%** | Street name, when the seller chose to publish one. Roughly half of Portuguese ads deliberately withhold the exact street |
| `city` | string | 100% | City or parish |
| `region` | string | 100% | District / province |
| `images` | string\[] | 100% | Listing photo URLs at the largest available resolution |

#### Listing Source & Flags

| Field | Type | Availability | Description |
|-------|------|--------------|-------------|
| `agencyName` | string | **89%** | Listing agency name. Absent for private sellers (use `isPrivateOwner` to tell them apart) and for the few agency ads with no agency record |
| `agencyType` | string | 89% | Agency type — present whenever `agencyName` is |
| `isPrivateOwner` | boolean | 100% | True when posted by a private owner rather than an agency |
| `isPromoted` | boolean | 100% | Promoted / featured listing |
| `isExclusive` | boolean | 100% | Exclusive-offer listing |
| `isDevelopment` | boolean | 100% | New-construction / development project |
| `developmentTitle` | string | **~2%** | Development name — only on the small share of rows that are part of a named new-build project |

#### Dates & Provenance

| Field | Type | Availability | Description |
|-------|------|--------------|-------------|
| `dateCreated` | string | 100% | The day the listing **first** went live, never moved by a re-list (ISO 8601, UTC) |
| `lastRefreshedAt` | string | 100% | The **last** time the listing was re-activated or refreshed (ISO 8601, UTC) |
| `pushedUpAt` | string | **~48%** | The last time the seller paid to push the listing back up the results (ISO 8601, UTC). Absent on the many listings that were never bumped |
| `searchQuery` | string | 100% | The search that produced this row, as `transaction/propertyType/location` |
| `scrapedAt` | string | 100% | ISO-8601 timestamp of data collection |

Empty fields are removed from each row, so a listing without a development name, a floor or a street address simply omits those keys rather than carrying a blank. Check for a key's presence rather than for an empty string.

### Tips for Best Results

- **Start small, then scale.** Set `maxResults` to 50–100 on your first run to confirm the data fits your needs, then raise it — or set it to `0` to pull an entire search. A small first run is also the quickest way to see which optional fields your segment actually carries: floor numbers show up on flats, plot sizes on houses, and street addresses on roughly half of all ads.
- **Type the location however you say it.** Districts ("Porto"), councils ("Cascais", "Albufeira"), regions ("Algarve", "Alentejo", "Madeira"), English names ("Lisbon") and resort towns ("Vilamoura", "Estoril") all resolve, accents optional. A region is searched across every district it covers, so "Alentejo" pulls Beja, Évora and Portalegre in one pass. Type "Lisboa/Cascais" when a council name exists in two districts.
- **Filter on `bedrooms`, not `totalRooms`.** Portuguese listings are advertised in the "T" system, where T3 means three bedrooms. That is the number the `rooms` filter takes and the number `bedrooms` returns, so a T3 search gives you `bedrooms: 3`. `totalRooms` is Imovirtual's own count and adds the living room, so the same listing reads `4` there — use it for total-space comparisons, never as a bedroom filter. One caveat at the top of the scale: Imovirtual stops counting at "10 rooms or more", so rows carrying `roomsAreMinimum: true` hold a floor rather than an exact figure. They still match a `bedrooms >= 5` filter, as they should, but drop them before you calculate a price per bedroom — most are whole buildings.
- **Sort on `dateCreated`, not on the refresh date.** Portuguese sellers re-list aggressively, so a large share of any results page was re-activated today. `dateCreated` is the only one of the three dates that stays put, so build "listed in the last 7 days" alerts on it and use `lastRefreshedAt` when you want to spot sellers actively working an ad.
- **Rent prices live in `totalPrice`.** For rent searches, the monthly euro amount is in `totalPrice` — there's no separate rent field to read.
- **Filter at the source to control cost.** Price, area, and bedroom filters narrow the search on Imovirtual itself, so tighter filters mean fewer rows collected and a cheaper run.
- **Paste the results page, not a single listing.** Any filter you can set on the site — including ones not exposed in the guided builder — carries through when you paste the search URL, and the URL's filters win over the guided fields. Use the address of a page that lists many properties (`.../pt/resultados/...`); the address of one individual property has nothing to page through and returns no rows.
- **Separate new builds from resale.** Filter on `isDevelopment` downstream (or set `propertyType` to "New development") to isolate off-plan empreendimento inventory.

### Pricing

**From $2.50 per 1,000 results** — below the typical market rate for Imovirtual extraction, with the guided search builder included at no extra charge.

Apify's loyalty tiers each earn a lower per-result rate, and Gold subscribers pay the headline price:

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.30 | $0.28 | $0.27 | $0.25 |
| 1,000 | $3.00 | $2.80 | $2.65 | $2.50 |
| 10,000 | $30.00 | $28.00 | $26.50 | $25.00 |
| 100,000 | $300.00 | $280.00 | $265.00 | $250.00 |

These tiered rates take effect on 11 September 2026. Until that date every plan pays $2.50 per 1,000 results.

A "result" is any listing row in the output dataset. **No compute charges — you only pay per result returned.** Standard Apify platform fees depend on your plan.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is designed for legitimate real-estate research, market analysis, and lead generation. You are responsible for complying with applicable laws and Imovirtual's Terms of Service, including any rules on the reuse of listing content and personal data. Do not use collected data for spam, harassment, or any unlawful purpose, and respect data-protection regulations when handling agency or owner contact information.

# Actor input Schema

## `startUrls` (type: `array`):

Paste one or more Imovirtual search-results URLs (for example https://www.imovirtual.com/pt/resultados/comprar/apartamento/lisboa). This is the fastest way to get exactly the results you see on the site. When you provide URLs here, the guided 'Build a Search' fields below are ignored.

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

Are you looking for properties to buy or to rent? Used only when no Search URLs are provided.

## `location` (type: `string`):

Where to search. Type a district (Lisboa, Porto, Faro), a council (Cascais, Albufeira — or 'Lisboa/Cascais' to be exact), a region (Algarve, Alentejo, Madeira, Açores) or 'Portugal' for the whole country. Accents, capitals and English names ('Lisbon') all work. Regions are searched across every district they cover. If the place isn't recognised the run stops and tells you which forms to use, instead of finishing with an empty result.

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

Filter by property category. Mirrors Imovirtual's own categories. Choose 'Any' to include all types.

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

Only include listings at or above this price in euros — monthly rent when renting, total price when buying. Leave empty for no minimum. Used only with the guided 'Build a Search' fields; when you paste Search URLs, the URL controls the filters.

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

Only include listings at or below this price in euros. Leave empty for no maximum.

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

Only include properties with living area at or above this many square metres. Leave empty for no minimum.

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

Only include properties with living area at or below this many square metres. Leave empty for no maximum.

## `rooms` (type: `array`):

Only include listings with these bedroom counts, in the Portuguese 'T' typology — T3 means 3 bedrooms, T0 is a studio. Whatever you pick here comes back in each row's `bedrooms` field. Rows also carry `totalRooms`, Imovirtual's own count, which adds the living room and is therefore one higher (a T3 has 3 bedrooms and 4 total rooms). T5+ is open-ended, and so is Imovirtual's own top bracket at the other end of the scale: listings it files under '10 rooms or more' carry no published exact figure, so they come back with `roomsAreMinimum: true` and a `bedroomsLabel` of '9+' — on those rows the numbers are floors, not counts. Select several to combine. Leave empty for any number of bedrooms.

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

Maximum number of listings to collect per search or URL. Use 50-100 for a quick scan or a higher number for deep research. Results are collected in full pages, so the final page may overshoot this number by a few rows. When Property Type is 'Any type', this cap is shared across the property categories rather than applied to each one. Set to 0 for no cap (an internal safety limit of 50,000 is then applied).

## Actor input object example

```json
{
  "startUrls": [],
  "transaction": "buy",
  "location": "Lisboa",
  "propertyType": "apartment",
  "rooms": [],
  "maxResults": 100
}
```

# Actor output Schema

## `overview` (type: `string`):

Table of scraped listings with price, area, bedrooms, location and URL.

## `detail` (type: `string`):

All extracted fields for every listing.

# 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 = {
    "startUrls": [],
    "transaction": "buy",
    "location": "Lisboa",
    "propertyType": "apartment",
    "rooms": [],
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/imovirtual-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 = {
    "startUrls": [],
    "transaction": "buy",
    "location": "Lisboa",
    "propertyType": "apartment",
    "rooms": [],
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/imovirtual-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 '{
  "startUrls": [],
  "transaction": "buy",
  "location": "Lisboa",
  "propertyType": "apartment",
  "rooms": [],
  "maxResults": 100
}' |
apify call solidcode/imovirtual-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidcode/imovirtual-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/SCh07ksg69wo8pGft/builds/ylAXV5KqW5RVi6wP2/openapi.json
