# Standvirtual Scraper (`normdata/standvirtual-scraper`) Actor

Every car, motorcycle, van and motorhome for sale on Standvirtual Portugal: full specs, price with market evaluation and price drops, equipment, dealer name, address and website, and the municipality of every listing. 40 filters, no 1,000 result cap, and new-listing tracking.

- **URL**: https://apify.com/normdata/standvirtual-scraper.md
- **Developed by:** [Norm Data](https://apify.com/normdata) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.20 / 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

![Norm Data](https://raw.githubusercontent.com/FabriAV/normdata/refs/heads/main/assets/banner_norm.png)

## 🚗 Standvirtual Portugal Cars Scraper

Get every car, motorcycle, commercial vehicle, and motorhome for sale on **Standvirtual**, Portugal's biggest vehicle marketplace. Each listing comes with full specifications, the asking price with the site's own market price evaluation and recent price drops, the equipment list, and the dealer's name, address, and website. No login, no account.

Built for dealers, importers, car traders, and market analysts who need the whole Portuguese market, not a sample of it.

### 🎯 Who uses it?

#### 🏪 Car dealers and traders

Find cars priced below market or recently reduced, by make, model, district, and budget, and get told about new ones on every scheduled run.

#### 🌍 Importers and exporters

Compare Portuguese prices with other markets across thousands of listings, with year, mileage, power, and equipment for each car.

#### 📈 Market analysts and lenders

Track prices, stock, and price drops by make, model, fuel, and region, including electric range and battery size.

#### 🤝 Dealer services and B2B sales

Build a list of active dealers with their address, postal code, website, stock, and whether they are registered credit intermediaries.

### ✨ What it does

- **The whole market:** every listing that matches your search, with no cap on results. Cars, motorcycles, commercial vehicles, and motorhomes.
- **Vehicle filters:** several makes and models at once, keyword, new or used, body type, fuel, gearbox, traction, color, year, mileage, and power.
- **Where:** any of Portugal's districts, Madeira, and the Azores islands, or any of its 308 municipalities.
- **Price filters:** price range, below market or at market by the site's own evaluation, and recent price drops only.
- **Seller and history filters:** dealers or private sellers, ACAP certified dealers, manufacturer certified programs, national or imported, maximum previous registrations, VAT deductible, trade-in accepted, financing, complete service book, second key, non-smoker, particle filter, and classic cars.
- **Equipment filters:** 38 must-have items, such as Apple CarPlay, reversing camera, heated seats, adaptive driving aids, and EV fast charging.
- **New listing tracking:** schedule the same search and each run returns only the listings that appeared since the last one.
- **Look up:** refresh listings you already know from their URL.

Missing source values are returned as `null`, never invented.

### Why this scraper

- **No 1,000 result limit.** Get every match, up to the entire marketplace of more than 40,000 cars.
- **Price intelligence on every row:** the site's own below, in, or above market evaluation, the price drop percentage, and the price before the drop.
- **Full listing details:** description, 25 specifications including CO2, consumption, warranty, and electric range, the complete equipment list, and every photo.
- **Dealer data built in,** not sold as an add-on: company and stand name, address, postal code, coordinates, website, logo, years on Standvirtual, ACAP certification, brand certified program, and Bank of Portugal credit intermediary number.
- **The municipality of every listing,** even though the site only shows the parish, so you can filter and group by concelho.
- **40 filters,** covering everything the site offers that matters for buying and analysis.
- **Private sellers stay private:** listings from private sellers are included, with no name, address, phone, or exact location.

### How it compares

| Capability | This actor | Other Standvirtual scrapers |
|---|:--:|:--:|
| Make, model, price, year, mileage, fuel, gearbox | yes | yes |
| **Results per run** | **unlimited** | up to 1,000 |
| **Several makes and models in one run** | **yes** | one |
| **District, island, and municipality filters** | **yes** | no |
| **Market price evaluation and price drops** | **yes** | no |
| **Description, equipment list, all photos** | **yes** | no |
| **Dealer name, address, website, credit intermediary** | **yes** | seller type only |
| **VAT, trade-in, financing, history, and equipment filters** | **yes** | no |
| **Motorcycles, commercial vehicles, motorhomes** | **yes** | cars only |
| **Only new listings on scheduled runs** | **yes** | no |

### 📦 What data you get

| Entity | Useful fields |
| --- | --- |
| Vehicle | Title, description, vehicle type, make, model, version, sub-model, year, registration month, mileage, fuel, gearbox, gears, engine size, power, body, color, doors, seats, traction. |
| Efficiency | CO2 emissions, urban and extra-urban consumption, battery capacity, and electric range. |
| Condition | New or used, imported, previous registrations, warranty in months, service book, second key, non-smoker, particle filter, classic. |
| Price | Asking price in euros, negotiable, market price evaluation, price drop percentage, and the price before the drop. |
| Deal terms | VAT deductible, financing available, and trade-in accepted. |
| Dealer | Company name, stand name, ID, address, postal code, coordinates, website, logo, year joined, ACAP certification, brand certified program, and credit intermediary status and number. |
| Location | Locality (parish), municipality, and district of every listing. |
| Media | Main photo, photo count, and every photo URL. |
| Listing | Equipment list, badges, listing link, and the dates it was published, first published, and last updated. |

Every record includes `scraped_at` (UTC). Download your dataset from Apify as CSV, JSON, Excel, or XML.

### 💡 Use cases

#### 🏪 BMW and Audi diesels under €30,000 from 2018, priced below market

```json
{ "makes": ["BMW", "Audi"], "fuelTypes": ["diesel"], "priceMax": 30000, "yearFrom": 2018, "priceEvaluation": "below" }
```

#### 🔔 Every new Tesla listed in Lisboa or Porto, on a daily schedule

```json
{ "makes": ["Tesla"], "districts": ["lisboa", "porto"], "onlyNewListings": true }
```

#### 📉 Recent price drops on automatic SUVs from dealers

```json
{ "bodyTypes": ["suv"], "gearboxes": ["automatic"], "sellerType": "dealer", "priceDropsOnly": true }
```

#### 🧾 VAT deductible company cars with CarPlay and a reversing camera

```json
{ "conditionFlags": ["tax_deductible"], "equipment": ["apple_carplay", "rear_view_camera"], "yearFrom": 2021 }
```

#### 🏍️ New motorcycles in the whole country

```json
{ "category": "motos", "condition": "new" }
```

#### 🏘️ Every car for sale in Matosinhos and Vila Nova de Gaia

```json
{ "municipalities": ["Matosinhos", "Vila Nova de Gaia"] }
```

#### 📊 A fast market snapshot of every electric car, search fields only

```json
{ "fuelTypes": ["electric"], "includeDetails": false }
```

### ⚙️ How the input is organised

**Maximum results** sits at the very top, since it applies no matter what you're doing. Leave it empty to collect every match. Below it, the form is split into eight numbered sections:

| Section | What it's for |
| --- | --- |
| **1 · What to do** | Search for vehicles or look up known listings. |
| **2 · Vehicle** | Vehicle type, makes, models, keyword, new or used, body, fuel, gearbox, traction, and color. |
| **3 · Where** | Districts, islands, and municipalities. |
| **4 · Price, year, and mileage** | Price, year, mileage, power, market price evaluation, and recent price drops. |
| **5 · Seller and history** | Dealers or private sellers, certified programs, origin, previous registrations, and deal and history flags. |
| **6 · Equipment** | Must-have equipment. |
| **7 · Output and tracking** | Full listing details, only new listings, and sort order. |
| **8 · Look up** | Listing URLs to refresh directly. |

Description, color, warranty, equipment, photos, and dealer address come from each listing's full page, so keep **Include full listing details** on when you need them. The filters themselves work either way.

New cars that a brand sells through its own store on Standvirtual open the store page instead of a listing. They are still returned, marked as new, with their search fields and a link to the store page.

> **Apify Free plan:** every run is limited to a fixed 10-row sample. Upgrade your Apify plan to run your own settings.

### 🛡️ Limits & responsible use

This Actor reads only public Standvirtual listings. It never signs in and never contacts sellers.

Dealer details are business information. Listings from private sellers are included without the seller's name, address, phone, or exact location. Seller phone numbers are not collected for anyone. Use the data for relevant business purposes, respect Standvirtual's terms, and do not republish listings.

Runs are paced to stay gentle on the site. About 1,000 listings with full details load in around a minute, and a search-only list is faster still.

A listing that no longer exists in Look up mode is not written to the dataset, so it is never charged. It is listed in the run log and in the `NOT_FOUND` record of the run's key-value store.

### 📧 Contact

Need a scraper for a different site, or found something wrong with this one? norm.data.scrapers@gmail.com

### Local development

```bash
bun install
bun test
bun run src/main.ts
```

# Changelog

This Actor's version history is a separate document: https://apify.com/normdata/standvirtual-scraper/changelog.md

# Actor input Schema

## `maxItems` (type: `integer`):

Caps how many listings this run writes. Leave empty to collect every match.

## `mode` (type: `string`):

Search builds a list of vehicles for sale. Look up refreshes specific listings you already know.

## `category` (type: `string`):

Cars, motorcycles, commercial vehicles, or motorhomes.

## `makes` (type: `array`):

One or more makes as you would write them, e.g. "BMW", "Mercedes-Benz", "VW", "Tesla". A misspelled make stops the run with suggestions. Leave empty for all makes.

## `models` (type: `array`):

Models of the makes above, as the site names them, e.g. "Série 3", "Classe C", "Golf", "Model 3". Needs at least one make.

## `keyword` (type: `string`):

Free text search, e.g. "GTI", "AMG", "M Sport", "7 lugares".

## `condition` (type: `string`):

Only new or only used vehicles.

## `bodyTypes` (type: `array`):

Only these body types.

## `fuelTypes` (type: `array`):

Only these fuel types.

## `gearboxes` (type: `array`):

Manual, automatic, or both.

## `tractions` (type: `array`):

Front, rear, or all-wheel drive.

## `colors` (type: `array`):

Only these exterior colors.

## `districts` (type: `array`):

Only these Portuguese districts or islands. Leave empty for all of Portugal.

## `municipalities` (type: `array`):

Only these municipalities (concelhos), e.g. Cascais, Matosinhos, Vila Nova de Gaia. Only their district is searched, so it stays fast.

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

Lowest asking price in euros.

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

Highest asking price in euros.

## `yearFrom` (type: `integer`):

First registration year, e.g. 2018.

## `yearTo` (type: `integer`):

First registration year, e.g. 2023.

## `mileageMin` (type: `integer`):

Lowest mileage in km.

## `mileageMax` (type: `integer`):

Highest mileage in km, e.g. 100000.

## `powerMin` (type: `integer`):

Lowest engine power in horsepower.

## `powerMax` (type: `integer`):

Highest engine power in horsepower.

## `priceEvaluation` (type: `string`):

Uses the site's own market price evaluation for each listing. "Below market" finds the deals.

## `priceDropsOnly` (type: `boolean`):

Only listings whose price was recently lowered, with the drop percentage and the price before.

## `sellerType` (type: `string`):

Dealers come with their name, address, website, and logo. Private sellers are listed without any personal details.

## `brandProgram` (type: `string`):

Only cars sold under a manufacturer's certified used car program.

## `origin` (type: `string`):

National cars were first registered in Portugal.

## `maxOwners` (type: `string`):

How many times the car was registered before, a proxy for the number of previous owners.

## `conditionFlags` (type: `array`):

Every one chosen must apply, e.g. VAT deductible, accepts trade-in, complete service book, second key.

## `equipment` (type: `array`):

Every item chosen must be fitted, e.g. Apple CarPlay, reversing camera, heated seats.

## `includeDetails` (type: `boolean`):

Opens every listing for its description, full specifications, equipment list, all photos, and the dealer's address, website, and credit intermediary status. Turn off for a faster list with the search fields only.

## `onlyNewListings` (type: `boolean`):

Remembers what this same search returned before, so a scheduled run returns only new listings. The first run returns everything and sets the starting point.

## `sort` (type: `string`):

Order of results, the same options as on the site.

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

Standvirtual listing links, e.g. https://www.standvirtual.com/carros/anuncio/bmw-z4-ver-2-2i-ID8PXD63.html

## Actor input object example

```json
{
  "maxItems": 10,
  "mode": "search",
  "category": "carros",
  "makes": [
    "BMW"
  ],
  "condition": "any",
  "priceEvaluation": "any",
  "priceDropsOnly": false,
  "sellerType": "any",
  "brandProgram": "any",
  "origin": "any",
  "maxOwners": "any",
  "includeDetails": true,
  "onlyNewListings": false,
  "sort": "relevance_web"
}
```

# Actor output Schema

## `results` (type: `string`):

One dataset row per listing matched by search or looked up by URL.

# 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 = {
    "maxItems": 10,
    "mode": "search",
    "category": "carros",
    "makes": [
        "BMW"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("normdata/standvirtual-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 = {
    "maxItems": 10,
    "mode": "search",
    "category": "carros",
    "makes": ["BMW"],
}

# Run the Actor and wait for it to finish
run = client.actor("normdata/standvirtual-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 '{
  "maxItems": 10,
  "mode": "search",
  "category": "carros",
  "makes": [
    "BMW"
  ]
}' |
apify call normdata/standvirtual-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,normdata/standvirtual-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/6tL4EdLwZm6sfZidT/builds/66qITflokDhksRHdz/openapi.json
