# InvestorLift Scraper — Wholesale Deals, Emails & Phones (`memo23/investorlift-scraper`) Actor

Export InvestorLift wholesale deals: price, city, ARV, wholesaler. Optional published email and phone from the listing or company site. Active, sold history, or paste URLs. No login.

- **URL**: https://apify.com/memo23/investorlift-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.19 / 1,000 deal retrieveds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## InvestorLift Scraper — Wholesale Deals, Emails & Phones

Export public InvestorLift wholesale deals into one row per listing: asking price, city, ARV, margin, beds/baths, wholesaler, and (when they published it) email or phone. No login.

**Active**, **historical** (sold + pending), or paste deal URLs. HTTP-only.

### Why use this

The marketplace catalog is a single public JSON dump (~57k rows). This actor filters it, optionally loads each deal for description and wholesaler name, and copies contact details only when they appear on the listing or the company website.

### Supported inputs

- **Mode:** active listings, sold/pending history, or a pasted list of URLs / numeric IDs
- **Filters:** US state, city, min/max asking price, listed-from / listed-until
- **Enrich with details:** description, lot size, condition, wholesaler company and contact name
- **Find public contacts:** mailbox, phone, LinkedIn, company site — never invented

### How it works

1. Downloads `/marketplace/api/customer/api/properties`
2. Filters by mode, geography, price, and dates
3. Loads each deal JSON for description and wholesaler fields
4. Reads published email / phone from the listing text; if a company website is on the listing, fetches that page too
5. Writes one dataset row per deal

Street address and the full photo gallery stay behind InvestorLift login. We do not bypass that. `public_address` on the site is city / county / ZIP.

### Input configuration

| Field | Notes |
|---|---|
| `scrapeMode` | `active_only` (default), `historical`, `specific` |
| `dealIds` | URLs like `https://investorlift.com/marketplace/deal/341075` or a numeric id |
| `states` / `cities` | Empty = nationwide |
| `maxItems` | `0` = no cap. Free plan is capped at 20. |
| `enrichWithDetails` | Default on |
| `findSellerContacts` | Default off in schema; prefilled on |

### Output fields

`id`, `title`, `status`, `source`, `city`, `county`, `state_code`, `zip`, `latitude`, `longitude`, `price`, `arv_estimate`, `arv_percentage`, `gross_margin`, `bedrooms`, `bathrooms`, `sq_footage`, `year_built`, `lot_size`, `property_type`, `condition`, `description`, `days_on_il`, `page_views`, `published_at`, `expires_at`, `img_url`, `property_page_url`, `account_id`, `wholesaler_company`, `wholesaler_name`, `email`, `phone`, `website`, `linkedinUrl`

### Pricing events

| Event | When |
|---|---|
| `deal-retrieved` | Deal row, no published website / phone / email |
| `deal-with-seller-website` | Company website found, no mailbox or tel |
| `deal-with-seller-phone` | Published phone, no mailbox |
| `deal-with-seller-email` | Published mailbox |

Set the dollar amounts in Console after the first push.

### FAQ

**Do I need an InvestorLift account?** No.

**Why is street address empty?** InvestorLift only shows city / county / ZIP until you log in. We do not log in.

**Historical mode is slow.** The catalog is one request. Detail enrichment is one request per deal. Raise timeout and `maxItems` if you want tens of thousands of sold rows.

### ⚠️ Disclaimer

This actor collects information that InvestorLift publishes without a login. Use it in line with InvestorLift's terms, applicable law, and your own compliance rules. Contact details are copied only when the seller published them. We do not invent emails or phones.

### SEO Keywords

InvestorLift scraper, InvestorLift wholesale deals, off-market real estate scraper, wholesale property leads, InvestorLift API, ARV deals export, wholesaler email phone

# Actor input Schema

## `scrapeMode` (type: `string`):

<b>Active</b> — Current listings.<br><br><b>Historical</b> — Sold + pending (raise Timeout for large dumps).<br><br><b>Specific</b> — Only the URLs or IDs you paste below.

## `dealIds` (type: `array`):

Used only when Mode is <b>Specific</b>. One InvestorLift URL or numeric ID per line. Leave empty for Active / Historical.

## `states` (type: `array`):

Keep only deals in these states. Empty = nationwide.

## `cities` (type: `array`):

Keep only these city names (one per line, e.g. Tampa). Matching is case-insensitive. Empty = all cities.

## `minPrice` (type: `integer`):

Keep deals at or above this asking price. Leave empty for no minimum.

## `maxPrice` (type: `integer`):

Keep deals at or below this asking price. Leave empty for no maximum.

## `dateRangeStart` (type: `string`):

Keep deals listed on or after this day (YYYY-MM-DD). Empty = no start date.

## `dateRangeEnd` (type: `string`):

Keep deals listed on or before this day. Empty = no end date.

## `findSellerContacts` (type: `boolean`):

Copy a mailbox, phone or LinkedIn URL only when they are published on the listing or the company site. Rows with a mailbox bill as Deal with seller email.

## `enrichWithDetails` (type: `boolean`):

Load each deal for description, lot size, condition, and wholesaler name. Turn off to write catalog fields only.

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

Stop after this many matching deals. <b>0 = no numerical cap</b>. Free plan is capped at 20.

## `maxConcurrency` (type: `integer`):

How many deal pages to load at the same time.

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

Leave off. InvestorLift answers a normal request. Turn on only if a run starts getting blocked.

## Actor input object example

```json
{
  "scrapeMode": "active_only",
  "findSellerContacts": true,
  "enrichWithDetails": true,
  "maxItems": 8,
  "maxConcurrency": 5,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (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 = {
    "findSellerContacts": true,
    "maxItems": 8,
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/investorlift-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 = {
    "findSellerContacts": True,
    "maxItems": 8,
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/investorlift-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 '{
  "findSellerContacts": true,
  "maxItems": 8,
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call memo23/investorlift-scraper --silent --output-dataset

```

## MCP server setup

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