# LockerFox Storage Auction Scraper — Lots, Bids & Facilities (`scrapersdelight/lockerfox-scraper`) Actor

From $3.50 per 1,000 rows, no start fee. Every open storage-unit lien auction on LockerFox: current bid, exact UTC close time, unit size, contents, photos, plus the facility name, street, city, state, ZIP, phone and hours. 4,740 live lots at 1,005 facilities across 43 states, counted.

- **URL**: https://apify.com/scrapersdelight/lockerfox-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** E-commerce, Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.50 / 1,000 per row returneds

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

## LockerFox Storage Auction Scraper — Lots, Bids & Facilities

**Every open storage-unit lien auction on [lockerfox.com](https://www.lockerfox.com) as a clean row — current bid, exact close time, unit size, contents, photos, cleanout deposit and pickup window — with the facility's name, street, city, state, ZIP, phone and opening hours attached to each one.**

`$0.0035` per row. No run-start fee. A run that matches nothing costs nothing.

***

### What one row is

One row = **one storage unit up for auction**, joined to the facility selling it.

That join is the point. A storage-auction listing is only useful if you can act on it, and acting on it means knowing which facility to drive to and which number to call to pay. US self-storage lien statutes require the facility to publish the sale with its identity and location attached — Texas Property Code §59.044, Cal. Bus. & Prof. Code §21707, Fla. Stat. §83.806 and their equivalents in the other 40 states LockerFox covers. That is why the contact block on these rows is not "usually there": it is **100% filled across every lot we measured**.

Switch **Row type** to *Facilities* and one row becomes **one storage facility with a sale on the calendar** instead — the same contact block, plus its sale dates, its open lot ids and its bid range.

***

### Measured, not estimated

Everything below was counted on **2026-09-18** by walking the entire site — the sitemap, all 43 state schedule pages, and every one of the 1,004 facility pages. Nothing is extrapolated.

| | Counted |
|---|---|
| States LockerFox publishes | **43** (42 had stock on the day; West Virginia had none) |
| Storage facilities with a scheduled sale | **1,004** |
| Scheduled sale events on the calendar | **1,111** |
| Lots in total | **4,741** |
| — open for bidding right now | **3,778** |
| — announced, bidding not yet started | **963** |
| Facility pages that returned cleanly | **1,004 / 1,004** (zero errors) |
| Biggest states (open lots) | texas 421 · indiana 309 · florida 300 · massachusetts 285 · north-carolina 243 · pennsylvania 238 · georgia 171 · ohio 164 · illinois 160 · michigan 131 · california 120 · kentucky 116 |
| Smallest | mississippi 7 · north-dakota 5 · oregon 3 · kansas 2 · arizona 1 · wyoming 1 |

**This is a small, fast-churning corpus.** 3,778 open lots is the entire national inventory at any instant, and individual lots close within days. That makes this a **repeat-run product** — a nightly or hourly sweep of your states — not a one-off dump of a million rows. Price the value accordingly: one locker won usually pays for a lot of runs.

***

### Every field, with its measured fill

Fill percentages come from a **150-lot sample drawn evenly across the national census, spanning 34 states**, parsed from the raw bytes. `""`, `"N/A"`, `"-"` and `"—"` are counted as **not** filled. A field we cannot populate is not shipped at all — see *What we do not ship* below.

#### Identity

| Field | Fill | What it is |
|---|---|---|
| `lotId` | 100% | LockerFox's lot number, the id in `/auctions/details/<id>` |
| `detailUrl` | 100% | Direct link to the listing (null for lots not yet open) |
| `lotTitle` | 100% | e.g. `Lot #20942220 U-Lock Self Storage` |
| `listingStatus` | 100% | `open` (biddable now) or `openSoon` (announced, bidding not started) |
| `listingType` | 100% | `Lien Sale` (143/150) or `Manager's Unit` (7/150) |
| `biddingOpen` | 100% | `false` once the bidding window has passed |
| `biddingStartsLocal` | upcoming lots only | When bidding opens, e.g. `Sunday 9/27 9:00 AM` |
| `stateSlug`, `country` | 100% | `texas`, `US` |
| `scrapedAt` | 100% | ISO instant of capture |

#### The facility contact block — this is why the row sells

| Field | Fill | What it is |
|---|---|---|
| `facilityName` | **100%** | e.g. `U-Lock Self Storage` |
| `street` | **100%** | e.g. `762 US 77` |
| `city` · `state` · `zip` | **100%** | `Hallettsville` · `TX` · `77964` — all 150 ZIPs were 5 digits |
| `facilityPhone` | **100%** | All 150 matched `(NNN) NNN-NNNN`. The facility's own line, not LockerFox's switchboard |
| `facilityUrl` | 100% | The facility's page, listing all its open lots |
| `facilityMapUrl` | 100% | Google Maps link, percent-encoded so it actually opens |
| `facilityHours` | **99%** | All seven days as an object, including days the office is `Closed` |
| `facilityNotes` | **93%** | The free-text payment and cleanout instructions — *"Winners must call (361) 798-4141 to pay via credit/debit card. NO CASH. There is no office at the facility…"* |
| `pickupTime` · `pickupTimeHours` | 100% | `72 Hours` / `72`. Observed: 24h (12), 48h (74), 72h (63), 168h (1) |
| `sellerRatingStars` · `sellerReviewCount` | 71% | Star rating and review count where the facility has reviews. Observed stars: 5 (86), 4 (19), 3 (1), 2 (1) |
| `facilityVerifiedOn` | 71% | Date of the verified review, e.g. `Dec 13, 2022` |
| `otherAuctionsAtFacility` | 91% | How many other lots this facility has open — a one-trip signal |
| `scheduledSales` | 100% | The facility's sale calendar: date, time and address per event |
| `facilityOrgId` · `facilityId` | 100% | LockerFox's internal operator and facility ids, stable across runs |

#### Money

| Field | Fill | What it is |
|---|---|---|
| `currentBid` | **100%** | USD, read from the page's own numeric variable, not scraped off the rendered digits |
| `minimumBid` | **100%** | The opening bid the facility set |
| `nextBid` | 100% | What the next valid bid would be |
| `cleanoutDeposit` | **100%** | Refundable deposit. Observed: $100 (124), $150 (9), $0 (8), $200 (4), $50 (2), $250 (1), $300 (2) |
| `highBidder` | 49% overall — **100% of lots that have a bid** | The leading bidder's handle. Cross-tabbed on the sample: 74 of 74 lots with a bid had a named leader, 0 of 76 lots sitting at $0 did. The two sets are exactly complementary, so the blanks are real, not missed parses |
| `hasBid` | 100% | `true`/`false`, never a fabricated zero |
| `currencyCode` | 100% | `USD` |

#### Timing

| Field | Fill | What it is |
|---|---|---|
| `closesAtUtc` | **100%** | **An exact UTC instant.** Derived from the seconds-to-close the server itself puts in the page, so you never have to guess what `CDT` meant on a given date |
| `closesAtLocal` | 100% | `Closes Friday 9/18 5:00 PM CDT` as published |
| `biddingEndsLocal` | 100% | `Fri 9/18 5:00 PM CDT` as published |
| `timezoneAbbrev` | 100% | Observed: EDT (92), CDT (47), PDT (7), MDT (4) |
| `secondsRemaining` · `hoursRemaining` · `daysRemaining` | 100% on open lots | Countdown at capture time |

#### The unit

| Field | Fill | What it is |
|---|---|---|
| `unitSize` | 100% | `12 x 12` |
| `unitWidthFt` · `unitLengthFt` · `unitAreaSqFt` | 100% | Parsed and multiplied out — `12 x 12` → `144` sq ft, so you can filter and sort on size |
| `contents` | 95% | The facility's contents summary: `Clothes, Books, Boxes & Totes, Furniture, Household Goods, Tools & Workshop` |
| `contentCategories` | 95% | The same thing split into an array, ready to filter on |
| `unitDescription` | 63% | Extra free text where the facility wrote any |
| `photoUrls` · `photoCount` · `imageUrl` | 100% | Every distinct photo at full resolution. Observed 1–12 per lot, median 5. Deduplicated by asset, so the same photo at three render sizes counts once |

#### Bidding activity — switch on *Include live bid history*

| Field | Fill | What it is |
|---|---|---|
| `liveBid` · `liveHighBidder` · `auctionStatus` | 100% | Read live from LockerFox's own public bid database. `auctionStatus` was `OPEN` on all 150 open lots sampled |
| `totalBids` · `uniqueBidders` | 100% of lots with a bid | Bid count and distinct bidders |
| `bidHistory` | 100% of lots with a bid (74/74) | **Every single bid**: amount, date, bidder handle, and whether it was placed by hand or auto-raised by someone's proxy bid |

The page bid and the database bid were **identical on 150 of 150** lots, so the two sources cross-check each other.

#### Facilities mode adds

`nextSaleDate` · `nextSaleTime` · `openLotCount` · `openLotIds` · `upcomingLotCount` · `upcomingLotIds` · `nextBiddingOpensLocal` · `lowestCurrentBid` · `highestCurrentBid` · `totalCurrentBidValue` · `soonestLotClosesAtUtc`.

Measured across all 1,004 facilities: **phone 1,004/1,004**, **ZIP 1,004/1,004**, **full seven-day hours 991/1,004 (98.7%)**.

***

### What we do not ship, and why

Shipping a column of nulls is worse than not shipping it. LockerFox does not publish these, so they are cut:

- **`latitude` / `longitude`** — no coordinates anywhere on the site. Use `facilityMapUrl` or geocode `street, city, state, zip` yourself.
- **`totalViews` / `uniqueViews`** — view counts are not published.
- **`reservePrice`** — not published.
- **`salesTaxPercent`** — mentioned in prose in `facilityNotes` on some lots, never as a structured number.
- **`unitNumber`** — the unit's number at the facility is not published.
- **`postDate` / `activeDate`** — LockerFox publishes when a lot *closes*, not when it was listed.
- **`paymentOptions` as a structured list** — the payment terms are free text, and you get them verbatim in `facilityNotes` (93% fill) rather than a tidy but invented enum.
- **`facilityWebsite`, `facilityFeatures`** — not published.
- **A ZIP-radius search** — without coordinates, a radius would be a guess. `zipCodes` matches exact ZIPs instead.

***

### A real row

Not an example. This is lot 20942220, delivered by an actual run on 2026-09-18, trimmed only where noted.

```json
{
  "lotId": "20942220",
  "detailUrl": "https://www.lockerfox.com/auctions/details/20942220",
  "lotTitle": "Lot #20942220 U-Lock Self Storage",
  "listingStatus": "open",
  "listingType": "Lien Sale",
  "biddingOpen": true,
  "facilityName": "U-Lock Self Storage",
  "facilityUrl": "https://www.lockerfox.com/storage-auctions/us/texas/hallettsville/u-lock-self-storage/",
  "facilityOrgId": "2272893",
  "facilityId": "2272895",
  "street": "762 US 77",
  "city": "Hallettsville",
  "state": "TX",
  "zip": "77964",
  "country": "US",
  "facilityPhone": "(361) 798-4141",
  "facilityMapUrl": "https://www.google.com/maps/place/762%20US%2077,Hallettsville,TX,77964",
  "facilityHours": {
    "Monday": "8 AM - 8 PM", "Tuesday": "8 AM - 8 PM", "Wednesday": "8 AM - 8 PM",
    "Thursday": "8 AM - 8 PM", "Friday": "8 AM - 8 PM", "Saturday": "8 AM - 8 PM",
    "Sunday": "8 AM - 8 PM"
  },
  "facilityNotes": "IMPORTANT: Winners must call (361) 798-4141 to pay for their unit via credit/debit card. NO CASH. There is no office at the facility. After paying your high bid amount (plus any sales tax), you will be given a temporary gate code and access to the unit. Unit subject to a $100 cleanout deposit, which will not be charged if unit is fully emptied as required.",
  "sellerRatingStars": 5,
  "sellerReviewCount": 1,
  "facilityVerifiedOn": "Dec 13, 2022",
  "otherAuctionsAtFacility": 17,
  "scheduledSales": [
    { "saleDate": "9/18/26", "saleTime": "5:00 PM", "facilityName": "U-Lock Self Storage",
      "street": "762 US 77", "city": "Hallettsville", "state": "TX", "zip": "77964" }
  ],
  "currentBid": 710,
  "minimumBid": 20,
  "nextBid": 720,
  "highBidder": "melonmacaw94",
  "hasBid": true,
  "cleanoutDeposit": 100,
  "currencyCode": "USD",
  "closesAtUtc": "2026-09-18T21:59:58.728Z",
  "closesAtLocal": "Friday 9/18 5:00 PM CDT",
  "biddingEndsLocal": "Fri 9/18 5:00 PM CDT",
  "timezoneAbbrev": "CDT",
  "secondsRemaining": 9522,
  "hoursRemaining": 2.65,
  "daysRemaining": 0,
  "unitSize": "12 x 12",
  "unitWidthFt": 12,
  "unitLengthFt": 12,
  "unitAreaSqFt": 144,
  "contents": "Clothes, Books, Boxes & Totes, Furniture, Household Goods, Tools & Workshop",
  "contentCategories": ["Clothes", "Books", "Boxes & Totes", "Furniture", "Household Goods", "Tools & Workshop"],
  "unitDescription": "United must be emptied entirely by Sunday evening or you will be charged a cleanout fee. Special accommodations can be made for clients purchasing multiple units.",
  "pickupTime": "72 Hours",
  "pickupTimeHours": 72,
  "imageUrl": "https://dxy0itsww8gss.cloudfront.net/…/resize=width:1024/…/cDmatHRFSodwdYQfCKg7",
  "photoUrls": ["https://dxy0itsww8gss.cloudfront.net/…"],
  "photoCount": 1,
  "stateSlug": "texas",
  "detailFetched": true,
  "scrapedAt": "2026-09-18T19:21:16.728Z"
}
```

With *Include live bid history* on, the same row also carries:

```json
{
  "liveBid": 710,
  "liveHighBidder": "melonmacaw94",
  "auctionStatus": "OPEN",
  "totalBids": 71,
  "uniqueBidders": 4,
  "bidHistory": [
    { "bid": 20,  "date": "9/3", "bidder": "dexter1229", "bidSource": "M", "proxyPusher": null },
    { "bid": 30,  "date": "9/4", "bidder": "dexter1229", "bidSource": "P", "proxyPusher": "melonmacaw94" },
    { "bid": 710, "date": "9/17","bidder": "melonmacaw94","bidSource": "M", "proxyPusher": null }
  ]
}
```

***

### Inputs

| Input | Type | Default | What it does |
|---|---|---|---|
| `mode` | select | `lots` | `lots` = one row per auction · `facilities` = one row per facility with a sale |
| `states` | list | all 43 | Slugs (`texas`) or codes (`TX`). An unknown value is reported in `RUN_SUMMARY.warnings`, never silently dropped |
| `facilityUrls` | list | – | Restrict to named facilities, skipping the state walk |
| `lotIds` | list | – | Look up known lots directly and skip enumeration entirely — the cheapest way to re-check a watchlist |
| `cities` | list | – | Keep lots whose address line contains one of these |
| `zipCodes` | list | – | Keep lots at these exact ZIPs |
| `keywords` | list | – | Keep lots whose contents or title contain one of these |
| `listingStatus` | select | `any` | `open` (biddable now) · `openSoon` (announced) |
| `minCurrentBid` / `maxCurrentBid` | int | – | Bid range in USD |
| `bidState` | select | `any` | `noBidsYet` ($0, nobody has touched it) · `hasBids` |
| `minUnitAreaSqFt` / `maxUnitAreaSqFt` | int | – | Unit size range, derived from the published dimensions |
| `closingWithinHours` | int | – | "What can I still win today" |
| `fetchLotDetails` | bool | `true` | Off = ~4× faster, 16 fields null, same price per row |
| `includeBidHistory` | bool | `false` | Adds the live bid, leader, status and full bid history at no extra charge |
| `maxRows` | int | `50` | Hard cap on rows delivered **and charged**. Enumeration stops when it is reached |
| `concurrency` | int | `6` | Requests in flight, 1–12 |
| `proxyConfiguration` | proxy | Apify datacenter | See *Source and limits* |

#### Examples

Everything open in Texas and Oklahoma, cheap and closing today:

```json
{ "states": ["TX", "OK"], "maxCurrentBid": 100, "closingWithinHours": 24, "maxRows": 500 }
```

Untouched lockers — nobody has bid yet — containing tools or electronics:

```json
{ "states": ["FL"], "bidState": "noBidsYet", "keywords": ["tools", "electronics"], "maxRows": 200 }
```

Re-price a watchlist for a fraction of a cent, no enumeration:

```json
{ "lotIds": ["20942220", "20955693"], "includeBidHistory": true }
```

Every storage facility with a sale on the calendar in the Northeast, for the phone list:

```json
{ "mode": "facilities", "states": ["MA", "NH", "ME", "VT", "RI", "CT"], "maxRows": 500 }
```

Get in before the crowd — lots announced but not yet open for bidding:

```json
{ "states": ["GA", "PA"], "listingStatus": "openSoon", "maxRows": 300 }
```

The whole country:

```json
{ "maxRows": 5000 }
```

***

### Pricing

**$0.0035 per row delivered.** No run-start fee, no charge for anything you do not receive.

- Lots your filters exclude are dropped at the **listing-card stage, before any detail page is fetched**. That is deliberate: if filtering happened after the fetch, we would pay for candidates you never receive, and that cost would end up in the price. So a narrow filter genuinely costs less.
- Upcoming lots are detected on the card and never cost a detail request.
- Lot IDs that do not exist, pages that answer but publish no record, and lots we could not reach are kept in **three separate lists** in `RUN_SUMMARY` and charged nothing — because "no such lot", "no record published" and "we could not get there" mean three different things to someone working a list.
- `maxRows` is enforced against rows **actually produced**, not against internal batches, so a cap of 50 charges for exactly 50.

A full national sweep of all 3,778 open lots is about **$13.22** and finishes in roughly nine minutes.

***

### Source and limits — read this before you buy

**Where the data comes from.** The public pages of lockerfox.com: `/sitemap.xml`, each state's `/schedule` page, each facility page, and each lot's detail page. No login, no account, no paid proxy. Photos and contents summaries are uploaded by the facilities themselves, and LockerFox's own disclaimer notes some descriptions may be AI-generated — always check the photos.

**robots.txt.** `https://www.lockerfox.com/robots.txt` reads, verbatim:

```
User-agent: *
Crawl-delay: 5
Allow: /account/login/
Disallow: /auctions/
Disallow: /preview/
Disallow: /public-notices/
Disallow: /operators/?utm_campaign=Legal
Disallow: /account/
```

`Disallow: /auctions/` covers the lot **detail** page, which is the richest hop in Lots mode. The sitemap, state, city, `/schedule` and facility pages are all permitted. **Facilities mode never touches a `/auctions/` path at all**, and neither does Lots mode with `fetchLotDetails` off — both stay entirely inside the allowed part of the site. The `Crawl-delay: 5` directive is not honoured: at 6 concurrent requests a full national run takes about nine minutes, where a 5-second delay would make it about 6.7 hours. You should decide whether that trade is acceptable for your use.

**Blocking.** None observed. Across 1,250+ requests on 2026-09-18 — from a home IP, through an Apify datacenter exit, and through a US residential exit — nothing was blocked, challenged or rate-limited, and the bytes were identical on all three (state page 277,995 B, lot page 57,253 B on every route). No Cloudflare, no CAPTCHA, no JS challenge. Datacenter proxy is therefore the default; switch to residential only if your own network is treated differently.

**Session behaviour.** Lot detail pages need a session cookie that only a state-scoped index page will issue. The actor handles this per worker and re-establishes it automatically. You will not see it, but it is the reason a naive scrape of this site returns zero rows.

**Honest limits.**

1. **The corpus is small and churns fast.** 3,778 open lots nationwide; individual lots close within days. This is a monitoring feed, not a bulk dataset.
2. **No coordinates, so no radius search.** See *What we do not ship*.
3. **Bids and countdowns are live values.** `currentBid` and `secondsRemaining` were true at `scrapedAt` and will have moved by the time you read them.
4. **A lot can close between enumeration and fetch.** When it does, the site stops rendering the countdown; the row comes back with `biddingOpen: false` and the lot is listed in `RUN_SUMMARY.closedSinceEnumerated` rather than silently carrying a stale time.
5. **Upcoming lots are genuinely thinner.** LockerFox publishes no detail page and no photos for a lot until bidding opens, so `openSoon` rows carry the card fields only. They are flagged, never padded.
6. **`contents` is the facility's summary, not an inventory.** 95% fill, and the facility wrote it.
7. **Seller ratings exist for 71% of lots.** A blank means the facility has no reviews, not that we failed to read them.
8. **West Virginia has a live page and zero stock.** Four other states were in single digits on the measurement day. A state filter returning nothing is usually the truth, and `RUN_SUMMARY` will say so.
9. **`maxRows` on an unfiltered national run takes states in alphabetical order, not a random sample.** The walk follows the sitemap, so `{ "maxRows": 60 }` with no `states` returns Alabama, Arkansas, Arizona and California — not 60 lots spread across the country. That is deliberate (it is what makes a small cap cheap: enumeration stops early instead of walking all 1,004 facilities first). If you want a specific area, name it in `states`; if you want everything, set `maxRows` to 5000.

***

### Who this is for

- **Storage-unit flippers and resellers** — find lockers worth bidding on, with the phone number to call the moment you win.
- **Liquidators and clean-out crews** — `facilityNotes` tells you the payment method, the cleanout deposit and the pickup window before you commit.
- **Auction alert services** — run it on a schedule against your states and diff on `lotId`; every lot carries a stable id and an exact `closesAtUtc`.
- **Anyone already using a StorageTreasures feed** — LockerFox is a separate, independent platform, so this is net-new inventory rather than the same lots again.
- **Route planners** — `otherAuctionsAtFacility` and Facilities mode's `openLotIds` tell you where one trip wins several units.
- **Market researchers** — `bidHistory` gives you the complete price discovery path on every lot that has a bid, including which raises were automatic proxy bids.

***

### Output

- **Dataset** — one row per lot (or facility). Four ready-made table views: *Storage auction lots*, *Facility contacts*, *Facilities & sale calendar*, *Bidding activity*. Export JSON, CSV, Excel, or pull via API.
- **`RUN_SUMMARY`** in the key-value store — states walked, facilities found, sale rows read, lot cards seen, cards that passed your filters, rows delivered (= rows charged), the measured field fill **for your own run**, and the three separate "nothing" lists.

### Legal

This actor reads pages that lockerfox.com serves to any anonymous visitor. Lien-sale notices are published under state self-storage statutes precisely so that they are public. It collects no personal data about bidders beyond the public display handles the site itself shows next to bids, holds no credentials, and does not place bids. You are responsible for how you use the output, including any applicable marketing and contact rules.

# Actor input Schema

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

LOTS (default): current bid, exact close time, unit size, contents, photos, cleanout deposit, pickup window, plus the full facility contact block. FACILITIES: facility name, address, phone, 7-day opening hours, next sale date and time, open lot count and lot ids, and the bid range across its open lots.

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

State slugs ("texas", "north-carolina") or two-letter codes ("TX", "NC"). Multiple entries are OR-ed. Anything the site does not publish is reported in RUN\_SUMMARY.warnings rather than silently dropped. Leave empty for all 43 states.

## `facilityUrls` (type: `array`):

Restrict the run to named facilities, skipping the state walk entirely. Paste the facility page URL or its path, e.g. "https://www.lockerfox.com/storage-auctions/us/texas/hallettsville/u-lock-self-storage/". Takes precedence over States.

## `lotIds` (type: `array`):

Look up known lots directly and skip enumeration completely — the cheapest way to re-check prices on a watchlist. The lot ID is the number in /auctions/details/<id>, e.g. "20942220". Overrides States and Specific facilities.

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

Keep only lots whose facility address line contains one of these (case-insensitive), e.g. \["austin", "san antonio"]. Applied to the listing card before any detail page is fetched, so filtered-out lots cost you nothing.

## `zipCodes` (type: `array`):

Keep only lots whose facility address line contains one of these ZIP codes, e.g. \["78701", "77964"]. Exact 5-digit strings; there is no radius search because LockerFox does not publish facility coordinates.

## `keywords` (type: `array`):

Keep only lots whose contents summary or title contains one of these (case-insensitive), e.g. \["tools", "electronics", "appliances"]. Multiple entries are OR-ed. The site's own contents vocabulary includes: Appliances, Bags, Books, Boxes & Totes, Clothes, Electronics, Furniture, Household Goods, Misc Items, Sporting Goods, Tools & Workshop, Toys.

## `minCurrentBid` (type: `integer`):

Keep only lots already bid at or above this. Measured spread on a 59-lot national sample: $0 on 16 of 59, then $10-$190, with the busiest facility lot at $710.

## `maxCurrentBid` (type: `integer`):

Keep only lots at or below this — the bargain filter. Combine with "No bids yet" to find units nobody has touched.

## `listingStatus` (type: `string`):

LockerFox lists two kinds of lot. OPEN lots are biddable now and have a full detail page. OPENING SOON lots are already announced with a facility, address, unit size and contents summary, but the site publishes no detail page and no photos until bidding starts, so those rows carry the card fields only and say so via listingStatus. Measured on 2026-09-18: 3,778 open and 963 opening soon, 4,741 lots in all.

## `bidState` (type: `string`):

Measured on a 59-lot national sample: 16 sat at $0 with no bidder, 43 had a bid and a named leading bidder. The two sets are exactly complementary — there were no lots with a bid and no bidder, or a bidder and no bid.

## `minUnitAreaSqFt` (type: `integer`):

Derived from the unit's published dimensions: a "10 x 15" unit is 150 sq ft. Use it to skip lockers too small to be worth the trip.

## `maxUnitAreaSqFt` (type: `integer`):

Derived from the unit's published dimensions. Use it to skip units bigger than your van.

## `closingWithinHours` (type: `integer`):

Keep only lots whose countdown is under this many hours — the "what can I still win today" filter. Read from the listing card's own countdown, so it costs nothing to apply.

## `fetchLotDetails` (type: `boolean`):

ON (recommended, the default): one extra request per lot buys the exact UTC close time, listing type, pickup window, cleanout deposit, minimum bid, the full photo gallery, the unit description, the facility's 7-day opening hours, its seller rating and the free-text payment/cleanout instructions. OFF: about four times faster and lighter, but 16 fields come back null for every row at the same price per row — only worth it for a fast price sweep.

## `includeBidHistory` (type: `boolean`):

Adds liveBid, liveHighBidder, auctionStatus, totalBids, uniqueBidders and the complete bidHistory array (every bid with its amount, date, bidder handle and whether it was a manual or an automatic proxy raise). Read from LockerFox's own public bid database — no login, no extra charge. Measured on a 59-lot sample: the node answered for 59 of 59 lots, and carried a bid history for all 43 lots that had received a bid.

## `maxRows` (type: `integer`):

Hard cap on rows delivered AND charged. Enumeration stops as soon as the cap is reached, so a small cap is genuinely cheap — it does not walk the country first. The whole national inventory was 4,740 lots / 1,005 facilities on 2026-09-18, so 5000 comfortably covers "everything".

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

Requests in flight. Measured 30 requests/second at 6 with zero errors across 1,250+ requests. Note that lockerfox.com/robots.txt asks for a Crawl-delay of 5 seconds, which no setting here honours — see the README's Source and limits section.

## `proxyConfiguration` (type: `object`):

Apify Proxy on the shared datacenter pool is the default because it was measured byte-identical to a residential exit and to a home IP on every surface (state page 277,995 B, lot page 57,253 B), with no Cloudflare, no CAPTCHA and no rate limiting across 1,250+ requests. Switch to RESIDENTIAL only if your own network is treated differently.

## Actor input object example

```json
{
  "mode": "lots",
  "states": [
    "texas"
  ],
  "facilityUrls": [],
  "lotIds": [],
  "cities": [],
  "zipCodes": [],
  "keywords": [],
  "listingStatus": "any",
  "bidState": "any",
  "fetchLotDetails": true,
  "includeBidHistory": false,
  "maxRows": 25,
  "concurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per open storage-unit lien auction (Lots mode) or per storage facility with a scheduled sale (Facilities mode): bid, exact UTC close time, unit size and contents, photos, cleanout deposit, pickup window, and the facility's name, street, city, state, ZIP, phone and 7-day opening hours.

## `runSummary` (type: `string`):

RUN\_SUMMARY: how much of the site was walked (states, facilities, lot cards seen, cards passing your filters), rows delivered and charged, measured field-fill for this run, and three separate lists for the three kinds of nothing — lot ids that do not exist, pages that publish no record, and lots that could not be reached. None of the three is charged.

# 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 = {
    "mode": "lots",
    "states": [
        "texas"
    ],
    "fetchLotDetails": true,
    "includeBidHistory": false,
    "maxRows": 25,
    "concurrency": 6
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/lockerfox-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 = {
    "mode": "lots",
    "states": ["texas"],
    "fetchLotDetails": True,
    "includeBidHistory": False,
    "maxRows": 25,
    "concurrency": 6,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/lockerfox-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 '{
  "mode": "lots",
  "states": [
    "texas"
  ],
  "fetchLotDetails": true,
  "includeBidHistory": false,
  "maxRows": 25,
  "concurrency": 6
}' |
apify call scrapersdelight/lockerfox-scraper --silent --output-dataset

```

## MCP server setup

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