# Movoto Scraper \[$3.50/1K💰] | MLS Listings | Agent Data (`ahmed_jasarevic/movoto-scraper`) Actor

Scrape Movoto.com home listings for any US city, neighborhood or ZIP and export price, beds, baths, sqft, address, MLS number, agent and brokerage as clean JSON. No browser, no blocks. Built for real-estate investors, agents and lead-gen teams.

- **URL**: https://apify.com/ahmed_jasarevic/movoto-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.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

## Movoto Scraper — Real Estate Listings & MLS Data API

Scrape **Movoto.com** real-estate listings for any US city, neighborhood or ZIP code and export price, beds, baths, square footage, address, **MLS number**, agent and brokerage as clean structured JSON. It runs on plain HTTP (no browser, no headless Chrome) against Movoto's server-rendered listing data, so a run is fast and cheap even at scale.

Built for US real-estate investors, agents, iBuyers and lead-generation teams who want Movoto coverage alongside Zillow/Redfin data.

### Main use cases

- **Real estate market research** — track asking prices, price-per-sqft and inventory across US cities and neighborhoods.
- **Real estate lead generation** — pull listing agents, brokerages and brokerage phone numbers for outreach lists.
- **Build a property database / MLS listings dataset** — expand a warehouse with Movoto active listings, MLS numbers and geo-coordinates.
- **Investment and comps analysis** — compare beds, baths, sqft, lot size, year built and days-on-market for comparables.
- **Competitor and price monitoring** — schedule recurring snapshots of a market to watch prices and listings change over time.

### How it works

Movoto server-side-renders its full Vue app state into every page as an `__INITIAL_STATE__` JSON blob. This actor requests the search pages you give it (city / neighborhood / ZIP), parses that embedded state and writes one row per listing to the dataset. Search pages return **50 listings each** and the actor follows pagination automatically until `maxItems` is reached. It uses a **CheerioCrawler** (HTTP-only, 256 MB) — there is no browser and no DOM scraping. Requests ride the standard Apify proxy when enabled and are paced with a 2-second same-domain delay.

> Detail pages are deliberately **not** scraped: they rate-limit (HTTP 403 after roughly 30 requests/minute) and made every run take minutes longer. Every field below already comes from the search data, so `description` is always `null`.

### Extract US Real Estate Listings For Market Research

Every Movoto search page embeds `state.pageData.listings[]` — a full listing card — plus `pageData.totalCount`. The actor parses each card into a dataset row covering price, beds/baths/sqft, lot size, structured address, latitude/longitude, property type, agent, brokerage and phone, photos, listing status, MLS number, year built, list date, days-on-Movoto and the detail URL. You supply the search URLs (e.g. `https://www.movoto.com/los-angeles-ca/`) and the actor paginates through the result pages itself.

### Build A Property Database Without The Movoto API

Movoto has no public listing API, and its pages sit behind **PerimeterX (px-captcha)** plus **CloudFront geo-blocking** — desktop browser User-Agents from datacenter or foreign IPs get a `403 px-captcha` page. This actor sidesteps both without a browser by sending a **consistent mobile Chrome session** (mobile User-Agent plus *matching* `sec-ch-ua-*` client hints) so Movoto returns the same `__INITIAL_STATE__` blob a real visitor's browser would receive. Mismatched hints (for example Windows platform hints on an Android User-Agent, which generic HTTP clients generate by default) are flagged by PerimeterX and blocked, so the header set is applied deliberately in `preNavigationHooks`.

For maintainers — surfaces checked and **not** used:

- `/api/dosearch/` (allowed in robots.txt) → still PerimeterX-walled from datacenter IPs.
- Algolia / third-party search backend → Movoto does not use one.
- `pi2.movoto.com` (the `boundaryUrl` in the state blob) → S3 image host, no listing API.
- `__NEXT_DATA__` / `__NUXT__` → not present; it is a Vue SSR app using `__INITIAL_STATE__`.
- Sitemaps (`/ssl/sitemap.xml`) confirm URL patterns and are a useful bulk-URL discovery aid, but the crawler starts from the search URLs you provide and paginates itself.

**Always enable the proxy in production** — Movoto's own VPS IP is CloudFront geo-blocked, and residential proxies are the next escalation step if the header set is tightened.

### Input Parameters

| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
| `startUrls` | array (requestListSources) | No (prefilled) | `https://www.movoto.com/los-angeles-ca/` | Movoto search-result page URLs (city / neighborhood / ZIP), e.g. `https://www.movoto.com/los-angeles-ca/`. |
| `maxItems` | integer | No | `50` | Maximum listings to scrape in total; result pages are followed automatically until it is reached. |
| `maxRequestsPerCrawl` | integer | No | `300` | Hard cap on total HTTP requests the crawler may make. |
| `proxy` | object (proxy) | No | `useApifyProxy: false` | Standard Apify proxy picker — enable (residential) for production runs. |

Free-plan users are capped at **10 listings** per run; paid users get the full `maxItems` range.

### Output Fields

One dataset item per listing (31 fields). The default `overview` view shows Title, Price, Beds, Baths, Sqft, City and URL.

| Field | Type | Description |
|---|---|---|
| `source` | string | Row origin; always `search` (detail pages are not scraped). |
| `title` | string | Listing headline. |
| `price` | integer | List price in USD. |
| `beds` | integer / null | Bedroom count (null for studios). |
| `baths` | integer / null | Bathroom count. |
| `sqft` | integer / null | Living area in square feet. |
| `lotSize` | integer / null | Lot size in square feet. |
| `address` | string | Full formatted address. |
| `streetAddress` | string | Street line. |
| `city` | string | City. |
| `state` | string | US state code. |
| `zip` | string | ZIP code. |
| `latitude` | number / null | Latitude. |
| `longitude` | number / null | Longitude. |
| `neighborhood` | string / null | Neighborhood name. |
| `county` | string / null | County. |
| `propertyType` | string / null | Display property type. |
| `propertyTypeCode` | string / null | Machine property-type code. |
| `agent` | string / null | Listing agent name. |
| `brokerage` | string / null | Brokerage / office name. |
| `brokeragePhone` | string / null | Brokerage phone number. |
| `photos` | array | Photo URLs. |
| `photoCount` | integer / null | Number of photos on the listing. |
| `description` | string / null | Always `null` — detail pages are not scraped. |
| `status` | string / null | Listing status, e.g. `Active`. |
| `mlsNumber` | string / null | MLS ID. |
| `yearBuilt` | integer / null | Year built. |
| `listDate` | string / null | Date listed on Movoto. |
| `daysOnMovoto` | integer / null | Days on market. |
| `propertyId` | string / null | Movoto internal property ID. |
| `url` | string | Listing detail URL. |

### Example Input And Output

**Input**

```json
{
  "startUrls": [
    { "url": "https://www.movoto.com/los-angeles-ca/" }
  ],
  "maxItems": 100,
  "maxRequestsPerCrawl": 300,
  "proxy": { "useApifyProxy": true }
}
```

**Output (one dataset row)**

```json
{
  "source": "search",
  "title": "11734 Sunshine Ter Studio City, CA 91604",
  "price": 1998000,
  "beds": 3,
  "baths": 3,
  "sqft": 2150,
  "lotSize": 4986,
  "address": "11734 Sunshine Ter Studio City, CA 91604",
  "streetAddress": "11734 Sunshine Ter",
  "city": "Studio City",
  "state": "CA",
  "zip": "91604",
  "latitude": 34.137952,
  "longitude": -118.388604,
  "neighborhood": "Studio City",
  "county": "Los Angeles",
  "propertyType": "Residential - Single Family",
  "propertyTypeCode": "single-family",
  "agent": "Gene Bush",
  "brokerage": "Coldwell Banker Realty",
  "brokeragePhone": "(310) 777-6200",
  "photos": ["https://pi.movoto.com/p/203/....webp"],
  "photoCount": 30,
  "description": null,
  "status": "Active",
  "mlsNumber": "26997899",
  "yearBuilt": 1937,
  "listDate": "2026-10-08 05:54:43",
  "daysOnMovoto": 0,
  "propertyId": "2902695",
  "url": "https://www.movoto.com/studio-city-ca/11734-sunshine-ter-..../"
}
```

### Integrations & Automation

Every Apify actor is reachable through the **Apify API**, and this one plugs into **webhooks**, **Zapier** and **Make** so results can flow into a Google Sheet, Airtable base, CRM or warehouse. For price monitoring and market research, run it on a **schedule** — a daily or weekly snapshot of your target cities is enough to track new listings and price changes, and recurring runs also improve the actor's Store recommendation signals.

### Related Actors

- [zillow-scraper](https://apify.com/maxcopell/zillow-scraper) — the largest Zillow listings scraper; pairs Movoto data with the broadest US market coverage.
- [zillow-detail-scraper](https://apify.com/maxcopell/zillow-detail-scraper) — adds full Zillow detail pages (description, gallery, agent) for listings Movoto does not expose.
- [zumper-scraper](https://apify.com/ahmed_jasarevic/zumper-scraper) — US rental listings to complement Movoto's for-sale inventory.
- [century21-scraper](https://apify.com/ahmed_jasarevic/century21-scraper) — another US real-estate source for a multi-portal property database.
- [coldwellbanker-scraper](https://apify.com/ahmed_jasarevic/coldwellbanker-scraper) — brokerage-level US listings with agent and office data.

### FAQ

#### Is there an official Movoto API?

Movoto does not publish a public listing API, and its pages are protected by PerimeterX plus CloudFront geo-blocking. This actor reads the server-rendered listing data directly through a consistent browser-like client, so you get structured listings without an API key and without paying for an anti-bot service or a browser.

#### What are the alternatives to this actor / this data source?

For US real-estate data you can combine this with Zillow, Redfin or Realtor.com scrapers. Movoto is one of the larger US portals (licensed nationwide) and is worth having alongside the others to widen coverage of active listings, MLS numbers and listing agents.

#### How do I get MLS number and agent data at scale?

Provide a city, neighborhood or ZIP search URL and set `maxItems`; the actor paginates through the search result pages automatically and returns the MLS number, listing agent, brokerage and brokerage phone for each listing, alongside price, size and geo-coordinates.

#### Does Movoto block scrapers?

Movoto uses PerimeterX and blocks datacenter/foreign IPs with a captcha page. This actor avoids that by sending a consistent mobile Chrome session and by routing through the Apify proxy; enable the proxy in production runs.

#### Best way to monitor US home prices by city?

Schedule this actor daily or weekly against your target city or ZIP URLs and store each run's dataset. Comparing runs over time gives you new-listing, price-change and days-on-market trends without manual checks.

#### Why is `description` null?

Listing descriptions live on detail pages, which Movoto rate-limits (HTTP 403 after roughly 30 requests/minute) and which slowed every run. Every other field is already present in the search data, so detail pages are skipped by design.

### SEO Keywords

movoto, movoto scraper, movoto api, movoto data, mls listings, mls number, real estate data, property data api, real estate listings api, real estate scraper, zillow scraper, home price monitoring, real estate lead generation, property database, us real estate listings, listing agent data, brokerage data

### For AI Agents & LLM Apps

Purpose: return one structured US real-estate listing row per Movoto listing, for a given city/neighborhood/ZIP search URL.

Minimal working input:

```json
{ "startUrls": [{ "url": "https://www.movoto.com/los-angeles-ca/" }], "maxItems": 50 }
```

Output fields: `source, title, price, beds, baths, sqft, lotSize, address, streetAddress, city, state, zip, latitude, longitude, neighborhood, county, propertyType, propertyTypeCode, agent, brokerage, brokeragePhone, photos, photoCount, description, status, mlsNumber, yearBuilt, listDate, daysOnMovoto, propertyId, url`.

Behaviors an agent should know:

- `startUrls` must be Movoto **search-result** URLs (city/neighborhood/ZIP). Detail-page URLs are not scraped.
- If `maxItems` is left unset it defaults to **50**; free-plan runs are capped at **10** listings regardless.
- `description` is always `null` by design — do not treat it as a missing/failed field.
- Enable the proxy for production; without it results depend on whether your IP is geo-blocked.
- `source` is always `search` and can be ignored.

Billing: pay-per-event — **$0.0035 per result** ($3.50 / 1,000 results) plus a $0.00005 actor-start event.

### Legal & Compliance Disclaimer

This actor is an independent tool and is **not affiliated with, endorsed by, or sponsored by Movoto**. It accesses only publicly available Movoto listing pages; it does not log in, bypass authentication, or solve CAPTCHAs on anyone's behalf. Users are responsible for ensuring their use complies with Movoto's Terms of Service and with applicable data-protection law. Where output includes agent or brokerage contact details, it must not be used for unsolicited commercial outreach in violation of applicable law (e.g. CAN-SPAM, TCPA, GDPR).

# Actor input Schema

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

Movoto search-result page URLs (city / neighborhood / ZIP), e.g. https://www.movoto.com/los-angeles-ca/

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

Maximum number of listings to scrape in total. Result pages are followed automatically until it is reached.

## `maxRequestsPerCrawl` (type: `integer`):

Hard cap on total HTTP requests the crawler may make.

## `proxy` (type: `object`):

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.movoto.com/los-angeles-ca/"
    }
  ],
  "maxItems": 50,
  "maxRequestsPerCrawl": 300,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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": [
        {
            "url": "https://www.movoto.com/los-angeles-ca/"
        }
    ],
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/movoto-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": [{ "url": "https://www.movoto.com/los-angeles-ca/" }],
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/movoto-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": [
    {
      "url": "https://www.movoto.com/los-angeles-ca/"
    }
  ],
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/movoto-scraper --silent --output-dataset

```

## MCP server setup

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