# LoopNet Commercial Listings Scraper (`usestring/loopnet-listings`) Actor

Collect LoopNet commercial real estate listings by market.

- **URL**: https://apify.com/usestring/loopnet-listings.md
- **Developed by:** [String](https://apify.com/usestring) (community)
- **Categories:** Real estate, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.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/platform/actors/running/actors-in-store#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

## LoopNet Scraper — commercial real estate for sale and for lease

This Actor scrapes LoopNet commercial real estate listings for any US market. Give it a market such
as `austin-tx` and the LoopNet Scraper returns around **25 listings per search** with the asking
price, price per square foot, building size, property type, year built, the listing broker and the
full address.

No LoopNet account, login or cookies are used — this reads what a logged-out visitor sees. Every
property type on the market search comes back in one pass, named in `propertyType`.

### What it returns

| Field | Type | Notes |
| --- | --- | --- |
| `listingId` | string | LoopNet's own listing ID — stable across runs, use it to de-duplicate |
| `title` | string | The listing's headline, e.g. a building or property name |
| `address` | string | Street address as the listing states it |
| `city`, `state`, `zipcode` | string | Split, not one blob |
| `price` | number | Whole-property asking price on a sale, e.g. `2750000` |
| `priceText` | string | The figure exactly as LoopNet quotes it, including ranges |
| `pricePerSqft` | number | Lease rate, which LoopNet quotes per square foot per year |
| `buildingSqft` | number | Building size |
| `propertyType` | string | LoopNet's own category, e.g. `Office`, `Retail`, `Industrial` |
| `yearBuilt` | number | |
| `brokerName` | string | Listing broker or brokerage where LoopNet names one |
| `detailUrl` | string | Link to the LoopNet listing page |
| `searchLocation`, `sourceUrl`, `collectedAt` | string | Provenance for every row |

A commercial listing often quotes a span — `"$649,180 - $5,750,515"`, or `"$12.00 - $14.00 SF/YR"` —
because one listing covers several units. Any single number taken from a span would be invented, so
those rows keep the span in `priceText` and leave `price` and `pricePerSqft` `null`.

### Input

```json
{ "locations": ["austin-tx", "Dallas, TX"], "listingType": "for-sale", "maxItems": 1000 }
```

| Field | Description |
| --- | --- |
| `locations` | LoopNet market slugs, e.g. `"austin-tx"`. `"Austin, TX"` is normalised to the same slug. Required, 1–100. |
| `listingType` | `for-sale` (default) or `for-lease`. |
| `maxItems` | Cap on dataset items. Default 1000. Free plans stop at 250 requests and 250 results — see below. |
| `concurrency` | Markets fetched in parallel. Default 2, maximum 5. |

### Use cases

- Commercial market comps — asking price and price per square foot side by side with building size
- Sourcing acquisition targets by property type and year built across several markets
- Broker and brokerage lead lists, from `brokerName` on every listing
- Lease-rate benchmarking per square foot within a submarket
- Tracking inventory and asking prices over time by re-running on a schedule

### Reliability

The LoopNet Scraper reads each listing from the search page's own listing cards and joins LoopNet's
schema.org listing data onto them by listing ID. The cards are the complete result set — the
schema.org block omits portfolio listings — while the schema.org block is what names the listing
broker, so neither source alone would produce the full field set.

A market that cannot be read is recorded in the run's `SUMMARY` under `failures` rather than silently
returning fewer rows, and a run where every market failed exits with an error.

There are no retries by design: the String Unblocker owns proxy rotation and anti-bot solver
selection, so a retry loop here would only re-roll the same block.

### Frequently asked questions

**Do I need a LoopNet account, API key or cookies?** No. The LoopNet Scraper reads the public LoopNet
market search as a logged-out visitor, and never signs in.

**How many listings does the LoopNet Scraper return per market?** Around 25 — one LoopNet search page
per market. Ten markets therefore return roughly 250 rows for ten requests.

**Why is `price` sometimes `null`?** Because the listing quotes a range rather than one figure, or
says "Contact for price". The quoted text is always kept in `priceText`.

**Where do lease rates appear?** In `pricePerSqft`, which is LoopNet's per-square-foot-per-year rate.
Sale listings put their whole-property figure in `price` instead.

**Does it return coordinates?** No. LoopNet's search cards carry city, state and ZIP code but no
latitude or longitude, so those fields are not emitted rather than guessed.

**Which countries does it support?** The United States only. This Actor targets `loopnet.com`.

### Limitations

One search page per market, so this is a market sampler rather than a full LoopNet crawl — run
several markets to widen coverage. Photos, broker phone numbers and email addresses, lot size,
coordinates, tenant details and the space-by-space availability breakdown of a multi-unit listing are
out of scope.

### Free plan limit

Runs started from an Apify **free plan** stop at **250 requests and 250 results**, and the run
reports that it reached the limit. Any paid plan runs the full input and `maxItems` you set.

The limit exists because this Actor fetches through our own infrastructure, which Apify does not
cover for free-plan runs. It binds on requests as well as results so that a large input list cannot
spend those fetches for rows the run will not return.

# Actor input Schema

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

LoopNet market slugs, e.g. austin-tx.

## `listingType` (type: `string`):

LoopNet listing category.

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

Global cap on dataset items. Runs started from an Apify free plan stop at 250 requests and 250 results; any paid plan runs the full amount.

## `concurrency` (type: `integer`):

Targets fetched in parallel.

## Actor input object example

```json
{
  "locations": [
    "austin-tx"
  ],
  "listingType": "for-sale",
  "maxItems": 1000,
  "concurrency": 2
}
```

# Actor output Schema

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

Collect LoopNet commercial real estate listings by market.

## `summary` (type: `string`):

Item count, failure count and every target that failed, with its error.

# 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 = {
    "locations": [
        "austin-tx"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("usestring/loopnet-listings").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 = { "locations": ["austin-tx"] }

# Run the Actor and wait for it to finish
run = client.actor("usestring/loopnet-listings").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 '{
  "locations": [
    "austin-tx"
  ]
}' |
apify call usestring/loopnet-listings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,usestring/loopnet-listings"
        }
    }
}

```

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/SZbmvbWnlKvbH1Srh/builds/1dre1uMxkbY3J1Y6b/openapi.json
