{
  "openapi": "3.0.1",
  "info": {
    "title": "LoopNet Scraper - Commercial Properties, Prices & Brokers",
    "description": "Scrape LoopNet commercial listings across the US, including office, retail, industrial, multifamily, land and hotels. Search by city or URL and extract 25+ fields including price, size, address, broker contacts and photos, with optional detail enrichment.",
    "version": "3.0",
    "x-build-id": "K41JC8jHV4Eti7KWv"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~loopnet-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-loopnet-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/abotapi~loopnet-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-loopnet-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/abotapi~loopnet-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-loopnet-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "search = build URLs from the search fields below; url = pass through your own LoopNet URLs. The price, size and sort filters apply in both modes.",
            "default": "search"
          },
          "site": {
            "title": "Site / region",
            "enum": [
              "co-uk",
              "com"
            ],
            "type": "string",
            "description": "Which LoopNet site to search. loopnet.co.uk covers the UK and international listings; loopnet.com covers US and Canada listings. Both work on Apify Proxy out of the box. In URL mode this is auto-detected from each URL.",
            "default": "co-uk"
          },
          "locations": {
            "title": "Locations",
            "uniqueItems": true,
            "type": "array",
            "description": "Search mode only. Type a plain name — \"London\", \"Los Angeles\", \"New York\", \"Paris\", \"Toronto\" and other major markets resolve automatically per site. Not recognized yet? Paste the exact LoopNet slug instead: for loopnet.com a city slug like \"los-angeles-ca\" or \"new-york-ny\" (or \"usa\" for nationwide); for loopnet.co.uk a full slug like \"london-england--united-kingdom\" (or \"united-kingdom\" for nationwide). A name that resolves to nothing is logged as a warning and passed through as-is, which is likely to return 0 results — use URL mode with a pasted LoopNet search URL as the reliable fallback. Multi-location supported. In URL mode this field is ignored, because each pasted URL carries its own location.",
            "items": {
              "type": "string"
            }
          },
          "listingType": {
            "title": "Listing type",
            "enum": [
              "for-sale",
              "for-lease",
              "auction"
            ],
            "type": "string",
            "description": "Search mode only. For Sale, For Lease (For Rent on the UK site), or Auction (US site only). In URL mode this field is ignored and the listing type is read from each pasted URL instead.",
            "default": "for-sale"
          },
          "propertyType": {
            "title": "Property type",
            "enum": [
              "all-commercial",
              "office-space",
              "retail-space",
              "industrial-properties",
              "multifamily",
              "land",
              "hotels",
              "restaurants",
              "healthcare-properties",
              "special-purpose",
              "sports-and-entertainment"
            ],
            "type": "string",
            "description": "Search mode only. Choose All Types for every category. In URL mode this field is ignored and the property type is read from each pasted URL instead.",
            "default": "all-commercial"
          },
          "urls": {
            "title": "LoopNet URLs",
            "uniqueItems": true,
            "type": "array",
            "description": "URL mode only. Paste loopnet.com or loopnet.co.uk search or listing URLs. The site is auto-detected per URL. The search-mode fields above (Locations, Listing type, Property type) are ignored here, but the price, size and sort fields below still apply to every pasted search URL. A pasted individual listing URL is saved as-is (and always billed as a detail fetch, whether or not \"Fetch detail pages\" is on, since a pasted listing URL is itself the detail page). Results continue from the page number in the URL onward. The default and prefill below carry one example of every supported URL shape — see the README's URL shapes table for the full list, including auctions and sort/price/size query params. Leaving this field untouched (or omitting it) in URL mode scrapes these 12 examples, one per shape, in order until Max listings is reached (default 20), so later examples may be cut or return no rows.",
            "default": [
              "https://www.loopnet.com/search/commercial-real-estate/los-angeles-ca/for-lease/",
              "https://www.loopnet.com/search/commercial-real-estate/los-angeles-ca/for-lease/2/",
              "https://www.loopnet.com/search/commercial-real-estate/usa/auctions/",
              "https://www.loopnet.com/search/office-space/los-angeles-ca/for-lease/",
              "https://www.loopnet.com/search/commercial-real-estate/los-angeles-ca/for-sale/?sk=x&sb=1",
              "https://www.loopnet.com/search/commercial-real-estate/usa/for-sale/",
              "https://www.loopnet.com/Listing/11340-W-Olympic-Blvd-Los-Angeles-CA/29122043/",
              "https://www.loopnet.co.uk/search/commercial-property/london-england--united-kingdom/for-rent/",
              "https://www.loopnet.co.uk/search/commercial-property/london-england--united-kingdom/for-rent/2/",
              "https://www.loopnet.co.uk/search/office-space/london-england--united-kingdom/for-rent/",
              "https://www.loopnet.co.uk/search/commercial-property/united-kingdom/for-sale/",
              "https://www.loopnet.co.uk/listing/10-prestons-rd-london/35346928/"
            ],
            "items": {
              "type": "string"
            }
          },
          "minPrice": {
            "title": "Minimum price",
            "minimum": 0,
            "type": "integer",
            "description": "Applies in both search mode and URL mode, including a pasted search URL. Keeps listings priced at or above this value. Listings whose results page shows no total price (a per sq ft or per month rent, for example) are kept. A pasted individual listing URL is always saved as-is."
          },
          "maxPrice": {
            "title": "Maximum price",
            "minimum": 0,
            "type": "integer",
            "description": "Applies in both search mode and URL mode, including a pasted search URL. Keeps listings priced at or below this value. Listings whose results page shows no total price (a per sq ft or per month rent, for example) are kept. A pasted individual listing URL is always saved as-is."
          },
          "minSqft": {
            "title": "Minimum size (sq ft)",
            "minimum": 0,
            "type": "integer",
            "description": "Applies in both search mode and URL mode, including a pasted search URL. Keeps listings with size at or above this value. Listings whose results page shows no size are kept. A pasted individual listing URL is always saved as-is."
          },
          "maxSqft": {
            "title": "Maximum size (sq ft)",
            "minimum": 0,
            "type": "integer",
            "description": "Applies in both search mode and URL mode, including a pasted search URL. Keeps listings with size at or below this value. Listings whose results page shows no size are kept. A pasted individual listing URL is always saved as-is."
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "default",
              "most-recent",
              "price-asc",
              "price-desc",
              "size-asc",
              "size-desc"
            ],
            "type": "string",
            "description": "Applies in both search mode and URL mode, including a pasted search URL. loopnet.com for-sale searches: price, size and most-recent orders are applied by the site itself, so the walk reads listings in that order across ALL pages (cheapest first, largest first, newest first...). loopnet.com for-lease searches: most recent and rent (price) orders are applied by the site; size orders listings within each results page only. loopnet.co.uk and auction searches: the order is applied within each results page only (the site has no order setting there). Site default keeps the site's own order.",
            "default": "default"
          },
          "listedInLastDays": {
            "title": "Listed in the last N days",
            "minimum": 1,
            "type": "integer",
            "description": "Only listings put on the market within this many days. loopnet.com: applied by the site itself (search mode, and pasted loopnet.com results URLs), so every page is a match. loopnet.co.uk: applied to the \"Date on Market\" each results card prints; cards without a date are left out. Leave empty for all dates."
          },
          "priceType": {
            "title": "Read min/max price as",
            "enum": [
              "total",
              "per-sqft",
              "per-acre",
              "per-unit"
            ],
            "type": "string",
            "description": "For-sale searches on loopnet.com. Whether Minimum/Maximum price above is the total asking price (default), or a price per sq ft, per acre or per unit. A per-unit filter is applied by the site; this actor does not re-filter it against the card's total price.",
            "default": "total"
          },
          "minCapRate": {
            "title": "Minimum cap rate (%)",
            "minimum": 0,
            "maximum": 100,
            "type": "number",
            "description": "For-sale searches on loopnet.com. Only listings with a published cap rate at or above this percentage, e.g. 5.5."
          },
          "maxCapRate": {
            "title": "Maximum cap rate (%)",
            "minimum": 0,
            "maximum": 100,
            "type": "number",
            "description": "For-sale searches on loopnet.com. Only listings with a published cap rate at or below this percentage."
          },
          "portfolioFilter": {
            "title": "Portfolio sales",
            "enum": [
              "include",
              "only",
              "exclude"
            ],
            "type": "string",
            "description": "For-sale searches on loopnet.com. Include multi-property portfolio sales (default), show only them, or leave them out.",
            "default": "include"
          },
          "condosFilter": {
            "title": "Condos",
            "enum": [
              "include",
              "only",
              "exclude"
            ],
            "type": "string",
            "description": "For-sale searches on loopnet.com. Include condo units (default), show only condos, or leave them out.",
            "default": "include"
          },
          "keyword": {
            "title": "Keyword",
            "type": "string",
            "description": "Search mode on loopnet.com. Free-text keyword the site matches against the listing text, e.g. \"parking\" or \"drive-in\"."
          },
          "subType": {
            "title": "Property sub-type (loopnet.com, for sale)",
            "enum": [
              "any",
              "live-work-space",
              "loft-space",
              "medical-offices",
              "mixed-use-properties",
              "data-centers",
              "flex-space",
              "refrigeration-and-cold-storage-properties",
              "research-and-development-properties",
              "service-properties",
              "showrooms",
              "telecom-facilities",
              "truck-stops-and-truck-terminals",
              "warehouses",
              "auto-shops",
              "banks",
              "day-care-centers-and-nurseries",
              "drug-stores",
              "gas-stations",
              "grocery-convenience-stores",
              "retail-buildings",
              "storefront-properties",
              "outlet-malls",
              "shopping-malls",
              "strip-malls",
              "dormitories",
              "mobile-home-parks",
              "assisted-living-facilities",
              "hospitals",
              "nursing-homes",
              "rehabilitation-centers",
              "senior-housing-facilities",
              "hostel",
              "hotels",
              "amusement-parks",
              "baseball-fields",
              "casinos",
              "golf-courses-and-driving-ranges",
              "horse-stables",
              "race-tracks",
              "skating-rinks",
              "theaters-and-concert-halls",
              "commercial-land",
              "farms",
              "industrial-land",
              "residential-land",
              "car-washes",
              "churches",
              "marinas",
              "parking-lots-and-garages",
              "schools",
              "self-storage-facilities"
            ],
            "type": "string",
            "description": "Narrow a loopnet.com for-sale search to one sub-type of property: warehouses, data centers, medical offices, strip malls, hotels, self-storage and more. Search mode only; it replaces the Property type above (each sub-type belongs to one property type). The site has no sub-types for lease, auction or loopnet.co.uk searches, so it is ignored there with a warning. Leave on Any for no sub-type filter.",
            "default": "any"
          },
          "fetchDetails": {
            "title": "Fetch detail pages",
            "type": "boolean",
            "description": "Adds extra fields per listing (coordinates, street address, broker phone, JSON-LD). The UK site already returns title, address, size, full description and broker names on the results page, so leaving this off is faster and cheaper.",
            "default": false
          },
          "maxPages": {
            "title": "Max pages per search",
            "minimum": 0,
            "type": "integer",
            "description": "Safety ceiling on results pages walked per location/URL. Leave empty to walk every result page. Pages stop early once Max listings is reached."
          },
          "maxListings": {
            "title": "Max listings (total)",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after this many listings across all searches. 0 = unlimited.",
            "default": 20
          },
          "splitLargeSearches": {
            "title": "Split searches past the 750-result cap",
            "type": "boolean",
            "description": "loopnet.com lists at most 750 results for one search. When a for-sale search hits that cap and Max listings asks for more, walk it again in price bands (splitting any band that is still capped) to reach listings beyond the first 750. Listings with no published price fall in no band. Off by default.",
            "default": false
          },
          "proxy": {
            "title": "Connection",
            "type": "object",
            "description": "The default Apify Residential connection works for both loopnet.co.uk and loopnet.com (regional connections are handled automatically). Your own proxy URLs are optional.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. Listings already collected there (matched by listing id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run. This continues ONE specific interrupted run — for recurring monitoring of the same search, use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily/weekly or other recurring monitoring of the SAME search. The first run returns every matching listing as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED listings. Turn on \"Emit unchanged\" or \"Emit expired\" only when you also want those returned (and billed). State is kept separately per site/location/filter/fetchDetails setup; use State key to name or deliberately share a monitoring campaign. Defaults off, so existing schedules are unaffected. To continue one specific interrupted run instead, use Resume from a previous run above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the site/locations/filters/fetchDetails — different searches then never mix state with each other."
          },
          "emitUnchanged": {
            "title": "Emit unchanged listings (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns — and bills — extra rows you already have, so leave it off unless you specifically want the full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired listings (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search — not when Max pages/Max listings capped it or when Resume was used. This returns — and bills — extra synthetic rows, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Optional, incremental mode only. Field names that should never, by themselves, mark a listing UPDATED — the field still comes back in every row, it is just excluded from change detection. Use a plain field name (e.g. \"exposureLevel\") or a dotted path into the nested commercial block (e.g. \"commercial.primaryImage\"), or \"commercial.*\" to ignore every field inside that block. Leave empty for the default: this actor's own fields measured stable across repeat scrapes are already excluded automatically, so you only need this for noise you personally observe.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}