PublicSurplus Scraper - Government Surplus Auction Data API avatar

PublicSurplus Scraper - Government Surplus Auction Data API

Pricing

from $6.23 / 1,000 results

Go to Apify Store
PublicSurplus Scraper - Government Surplus Auction Data API

PublicSurplus Scraper - Government Surplus Auction Data API

Extract open PublicSurplus government surplus auctions: live bid count and price, closing time, selling agency, pick-up address, photos, attached documents, condition and vehicle specs including VIN, mileage and an optional NHTSA VIN decode.

Pricing

from $6.23 / 1,000 results

Rating

0.0

(0)

Developer

ParseForge

ParseForge

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

ParseForge

PublicSurplus Scraper - Government Surplus Auction Data API

Scrape open government auctions from PublicSurplus. Every run returns a 20-field base row — id, title, price, currency, region, the full schedule, the lot type, the category, the condition grade and the selling agency — for one flat price. On top of that sit nine optional data blocks covering the other 68 fields: live bidding, the agency profile, the pick-up address, the sale terms, the item's own spec sheet, an NHTSA VIN decode, photos, documents and the description. Each one is off by default: if you do not tick it, you do not receive it and you are not charged for it. No login, no API key, no cookies. Export to CSV, JSON, Excel, or XML.

PublicSurplus is where roughly 5,700 open lots from US and Canadian cities, counties, school districts, universities, police departments and state agencies sit at any moment. It publishes no API. This Actor reads the same pages a buyer sees and turns them into one fixed schema.

Who uses itWhat they scrape PublicSurplus for
Dealers and resellersFleet vehicles and heavy equipment with VIN, odometer and running condition, filtered to lots closing today
Auction aggregatorsA deduplicated feed of every open lot in one schema, keyed on a stable auction id
Fleet and asset managersWhat comparable units actually sell for, by state, agency and category
Municipal procurement teamsWhat peer agencies are disposing of, and on what payment and pick-up terms
Price and market researchersBid counts, increments and reserve state across 232 categories and 68 regions

What it does

This Actor collects PublicSurplus auctions by keyword, category, state, agency, ZIP radius or exact URL, and returns each lot as a flat row. The 🔓 blocks below are optional and off unless you ask for them.

🔓 The selling agency, not just its name. (includeAgencyProfile) agencyId, the agency's storefront URL, its logo, and a link to every other lot it has open — so one row turns into a whole agency's catalogue.

🔓 The pick-up address split into columns. (includePickupLocation) Location name, street, city, state and ZIP as separate fields, plus PublicSurplus's map link. You can plan a collection route straight off the dataset.

🔓 Live bidding state. (includeBidding) bidCount, minimumBid, bidIncrement, the masked handle of the leading bidder with their years on the platform, and whether a reserve exists and has been met.

🔓 The agency's own vehicle block. (includeItemSpecs) vin, mileage, year, make, model, engine, transmission, tires and runningCondition as typed columns — plus the CARFAX link PublicSurplus prints beside the VIN.

🔓 An NHTSA VIN decode. (includeVinDecode) Tick it and every 17-character VIN gains 16 more columns from the US government's public vPIC database: body class, fuel type, cylinders, displacement, drive type, GVWR class, assembly plant.

🔓 Real-estate lots too. (includeItemSpecs) Parcel number, property type, zoning, lot size in acres and building size in square feet come back as typed fields on Real Estate lots.

🔓 Every photo, full resolution. (includeImages, includeAttachments) imageUrls holds the agency's uploads in order, not the listing thumbnail. Attached documents — titles, inspection reports, site maps — come back as name-and-URL pairs.

🏷️ All three lot types, in the base row. Ordinary bid auctions, fixed-price buy-it-now lots with their asking price, and multi-unit dutch auctions with the quantity on offer.

Results export to CSV, JSON, Excel, or XML, or stream from the API.

What you can do with PublicSurplus data

🚗 Source fleet vehicles by the numbers.

Filter to Motor Pool, onlyWithVin, mileage under your ceiling and endingWithinHours of 24, and you get a shortlist of vehicles closing today with the VIN already decoded.

📈 Track what surplus actually sells for.

Run it on a schedule and key on auctionId. bidCount and currentPrice climbing across runs is a live price curve; a lot that disappears has closed.

🗺️ Plan a collection route.

pickupCity, pickupState, pickupZip and the ZIP-radius filter let you buy only what you can physically collect.

🔔 Watch for new listings.

startedWithinHours asks PublicSurplus for lots that opened in the last hour, day or week. That is a new-listing monitor with one field and no diffing.

🏢 Follow specific agencies.

Put their agencyId values in agencyIds and the Actor walks each agency's whole open catalogue, 50 lots a page.

Why choose this scraper

What you get
88 fields per lotEvery field the public auction page publishes, verified against live pages rather than guessed. Twenty of them are the base row; the rest arrive block by block, as you ask for them.
Bids, not just pricesbidCount, bidIncrement, minimumBid, the leading bidder's masked handle and platform tenure, and reserve state.
The agency blockagencyId, storefront, logo, full pick-up address, accepted payment methods, card ceiling, deposit rule and the terms document.
Vehicle specs as columnsVIN, mileage, year, make, model, engine, transmission, tires and running condition — from the agency's own form, not parsed out of prose.
Nothing billed by surpriseA run left at its defaults charges exactly one per-row price. Nine optional blocks are each a checkbox and each its own line on the bill.
23 filters that cut the billThirteen go to PublicSurplus with the query; ten more run before the row is written. Rejected rows are never charged — and the filters read the complete row, so you can filter on bids, photos, documents or a VIN without buying those columns.
232 categories, 68 regionsAll 28 top categories and 204 sub-categories, 50 US states, DC, four US territories and 13 Canadian provinces and territories — every region the site lists — by name or by id.
No proxy, no loginPublicSurplus answers plain requests. The Actor runs proxy-free by default, so a run costs you nothing in proxy traffic.
Honest emptiesA field the agency did not fill in is absent, never a guessed value and never a null.
Four export formatsCSV, JSON, Excel, and XML, from the dashboard or the API.

How it compares

The competitor columns below reflect what each Actor's own public listing states, not a test run of it.

FeatureParseForgescrapersdelightlulzasaurcrawlerbros
Fields per lot88Lot, bid, location, close timeTitle, bid, location, category, close time, URL, imagesNot stated
Bid count, increment and minimumYesNot statedNot statedNot stated
High bidder handle and tenureYesNoNoNo
Reserve price stateYesNoNoNo
Selling agency id and pick-up addressYesLocation onlyLocation onlyNot stated
Vehicle VIN, mileage and conditionYesNot statedNot statedNot stated
NHTSA VIN decodeYes, 16 columnsNoNoNo
Real-estate parcel, zoning and lot sizeYesNoNoNo
Attached documentsYesNoNoNo
Fixed-price and Dutch lots flaggedYesNot statedNot statedNot stated
New-listing monitorstartedWithinHours filterYes, with Slack/email/webhook alertsNot statedNot stated
Base price per result$0.007$0.003$0.005$0.005
Optional blocks you can switch off9, each its own chargeNoNoNo

This Actor is the dearest of the four per row, and deliberately so: the base row alone carries fields the others do not return at all, and the deep data — bids, agency, address, documents, spec sheet, VIN decode — is priced block by block instead of being folded into everybody's bill. If all you need is a title-and-price feed, the cheaper Actors will do it more cheaply.

If you want alerting — a scheduled monitor that pushes new lots to Slack, email or a webhook — scrapersdelight's Actor does that and this one does not.

What a lot looks like

A run left at its defaults returns this — the base row, twenty fields, one flat price. Real record, unedited. (categoryId and categoryName are the two that only appear when the run browsed a category; a keyword search returns eighteen.)

{
"auctionId": "4066151",
"url": "https://www.publicsurplus.com/sms/auction/view?auc=4066151",
"title": "ADOT - D790 - 2002 FORD F450 TRUCK 1.5 TON 5TH WHEEL DRW 4X4",
"scrapedAt": "2026-08-20T17:27:58.087Z",
"currentPrice": 7300,
"currency": "USD",
"state": "AZ",
"auctionType": "bid",
"condition": "UNKNOWN",
"agencyName": "ADOT",
"categoryId": 4,
"categoryName": "motor pool",
"startsAt": "2026-08-18T03:00:00.000Z",
"endsAt": "2026-08-22T03:00:00.000Z",
"startedAtText": "Aug 17, 2026 09:00 PM MDT",
"endsAtText": "Aug 21, 2026 09:00 PM MDT",
"timeLeftSeconds": 120722,
"isEnded": false,
"mightExtend": true,
"thumbnailUrl": "https://d37qv0n5b4mbzm.cloudfront.net/sms/docviewer/cdnmainaucdoc/thumb-b/4066151/71388322"
}

Tick the blocks you want and the same row grows. With all nine on, a fleet vehicle comes back with 70 fields:

{
"auctionId": "4064156",
"title": "2020 Chevrolet Tahoe 4x2",
"currentPrice": 5600,
"bidCount": 35,
"minimumBid": 5700,
"bidIncrement": 100,
"highBidder": "F******1",
"highBidderYears": 0,
"agencyId": "294914",
"agencyUrl": "https://www.publicsurplus.com/sms/scottsdale,az/browse/home",
"agencyAuctionsUrl": "https://www.publicsurplus.com/sms/list/current?orgid=294914",
"pickupStreet": "9191 E San Salvador Dr",
"pickupCity": "Scottsdale",
"pickupState": "AZ",
"pickupZip": "85258",
"paymentMethods": ["Visa", "MasterCard", "Discover"],
"creditCardLimitUsd": 4000,
"bidDeposit": "REQUIRED",
"termsUrl": "https://www.publicsurplus.com/sms/docviewer/aucterms?auc=4064156",
"year": 2020,
"make": "Chevrolet",
"model": "Tahoe",
"mileage": 158773,
"vin": "1GNLCDEC8LR231706",
"engine": "5.3 Li 8V",
"transmission": "6 Automatic",
"runningCondition": "Starts, Runs, Drives",
"carfaxUrl": "https://secure.carfax.com/creditCard.cfx?partner=DVE_B&vin=1GNLCDEC8LR231706",
"vinBodyClass": "Sport Utility Vehicle [SUV]/Multipurpose Vehicle [MPV]",
"vinFuelType": "Gasoline",
"vinEngineCylinders": 8,
"vinDisplacementL": 5.3,
"vinGvwr": "Class 2E: 6,001 - 7,000 lb (2,722 - 3,175 kg)",
"vinPlantCountry": "UNITED STATES (USA)",
"imageCount": 25,
"imageUrls": ["https://d37qv0n5b4mbzm.cloudfront.net/sms/docviewer/cdnaucdoc/img/4064156/71341883"],
"attachmentCount": 0,
"description": "6,001-7,000 GVW Sport Utility - 3/4 Ton Public Safety ...",
"descriptionFormat": "text"
}

Configure the run

SettingWhat it does
keyword / keywordsWord or phrase to search for. PublicSurplus matches it against the title and the full description, so truck also finds a cabinet whose description mentions a hand-truck. Each extra keyword is its own search, merged and deduplicated.
category / categoryIdsOne of 28 categories or 204 sub-categories. Accepts the name (motor pool), a sub-category (motor pool > truck, or just truck), or the numeric id.
region / regionsState or province. Accepts the name (California), the code (CA), or the site's own all,ca.
agencyIdsWalk specific agencies' full catalogues instead of searching. Use the agencyId from any row.
auctionUrlsExact lots to fetch, skipping discovery. Accepts a full auction URL or the bare number.
maxItemsCeiling on rows written. Not a target — a narrow filter returns fewer.
maxPagesHow deep discovery may page into one search. A search page holds 25 rows, an agency page 50.
sortBy / sortDescendingClosing soonest, price, auction id, or title. Sent to PublicSurplus; with several keywords, categories or regions the merged set is sorted again before rows are written.
listingOnlySkip the lot's own page for a faster, shallower run — 13 fields straight off the listing, without the condition grade, agency name or start date. It does not change the price, and the page is read anyway if you tick a block or set a filter that needs it.
descriptionFormattext or html, for when the description block is on.
proxyConfigurationOff by default. PublicSurplus answers plain requests; enable only if your runs start getting rate-limited.

Optional data blocks

The base row is always there. Everything else is a checkbox, off by default, with its own line on the bill. A block you do not tick is neither written to the dataset nor charged for.

Switched on byWhat it adds
includeBiddingbidCount, openingPrice, minimumBid, bidIncrement, highBidder, highBidderYears, hasReserve, reserveMet, buyItNowPrice, quantity.
includeAgencyProfileagencyId, agencyAlias, agencyUrl, agencyAuctionsUrl, agencyLogoUrl. The agency's name is in the base row either way.
includePickupLocationpickupLocationName, pickupStreet, pickupCity, pickupState, pickupZip, mapUrl.
includeSaleTermspaymentMethods, paymentNote, creditCardLimitUsd, shipping, bidDeposit, termsUrl.
includeItemSpecsspecs plus the typed columns: year, make, model, mileage, vin, engine, transmission, tires, runningCondition, bodyStyle, manufacturer, hours, carfaxUrl, parcelNumber, propertyType, lotSizeAcres, buildingSizeSqFt, zoning. About 20% of lots carry a block.
includeVinDecodeThe 16 vin* columns from NHTSA vPIC. Works on its own — you do not need includeItemSpecs to get them.
includeImagesimageUrls and imageCount.
includeAttachmentsattachments and attachmentCount. About 6% of lots carry a document.
includeDescriptiondescription and descriptionFormat.

Narrow the run with filters

Every filter runs before the row is written, so rows you filter out are never charged — not even for the auction page the Actor had to read in order to apply the filter. The one thing a wide run still pays for is the listing-page events discovery spends finding candidates.

Filters read the complete row, before the optional blocks are stripped out. That means you can filter on data you are not buying: onlyWithVin, onlyWithBids, minBidCount, onlyWithImages and onlyWithAttachments all work with every block switched off. You pay for the rows that match, not for the columns used to find them.

Thirteen filters go to PublicSurplus with the query, so the lots they reject are never even downloaded:

FilterWhat it keeps
keyword / keywordsLots whose title or description contains the term.
category / categoryIdsLots in that category or sub-category.
region / regionsLots in that state, territory or province.
agencyIdsLots from those agencies.
priceMin / priceMaxLots whose current price falls in the range.
endingWithinHoursLots closing in 1, 6, 24, 120 or 240 hours — the five steps the site offers.
startedWithinHoursLots that opened in the last 1, 24, 48 or 168 hours.
zipCode + milesFromZipLots within a radius of a US ZIP code, in the steps the site offers from 20 to 1,000 miles.

Ten more run in the Actor, because PublicSurplus has no query parameter for them:

FilterWhat it keeps
auctionTypesbid, fixed-price or dutch. Read off the listing badge, so a rejected lot never costs a detail fetch.
statesLots in these two-letter regions. Cheaper than regions on a broad run, because it does not fan out into separate searches.
titleExcludesDrops lots whose title or description contains any of these words.
onlyWithBids / onlyWithoutBidsLots that have, or have not, been bid on.
minBidCount / maxBidCountLots inside a bid-count range.
onlyWithImagesLots the agency published with at least one photo.
onlyWithVinLots carrying a valid 17-character VIN.
onlyWithAttachmentsLots with an attached document.

Why discovery works the way it does

PublicSurplus's search endpoint is stateless: every filter has to ride on every request, page 2 included. The Actor sends the full query each time, which is why paging deep into a filtered search returns the filtered set rather than drifting back to everything.

Its listing pages give 25 rows each, and an unfiltered search runs about 230 pages deep — roughly 5,750 open lots site-wide, measured 20/08/2026. Lots open and close all day, so the Actor reads the pager off the page instead of assuming a page count, and stops on the first empty page. A single search therefore reaches the whole site; a category or region search reaches all of it several times over.

Closed auctions are not covered. PublicSurplus answers 401 for a closed lot unless you are logged in, so this Actor returns open lots only. A lot that closes mid-run is logged and skipped, never billed.

Pricing

This Actor is pay per event, and a run left at its defaults has exactly one per-row price. Every optional data block is off by default: if you do not tick it, you do not receive it and you are not charged for it. Nothing is billed for rows a filter rejected.

EventPriceWhen it fires
result-item$0.007One auction row. Covers the base row: id, URL, title, price, currency, region, the full schedule, lot type, category, condition grade, selling agency name and thumbnail — and the auction page read to get them.
listing-page$0.002One search or agency listing page read during discovery — 25 rows on a search, 50 on an agency. Charged per page, whatever the filters keep.
apify-actor-start$0.02Once when the run starts, per GB of memory.

Optional, and off unless you ask for them:

EventPriceSwitched on by
bid-data$0.0015includeBidding — bid count, opening and minimum bid, increment, high bidder, reserve state, buy-it-now price, Dutch quantity.
agency-profile$0.0008includeAgencyProfile — agency id, slug, storefront, logo, and a link to its other open lots.
pickup-location$0.0008includePickupLocation — location name, street, city, state, ZIP and the map link.
sale-terms$0.0006includeSaleTerms — payment methods, card ceiling, shipping, bid deposit, terms document.
item-specs$0.0012includeItemSpecs — the agency's attribute block, typed. ~20% of lots carry one.
vin-decode$0.0015includeVinDecode — 16 NHTSA vPIC columns. One extra request per vehicle.
image-set$0.0008includeImages — every full-resolution photo URL.
attachment-docs$0.0006includeAttachments — attached documents. ~6% of lots carry one.
description-text$0.0008includeDescription — the agency's full lot description.

A default run costs $0.007 per lot, or $7.00 per 1,000, plus $0.002 for each 25-row listing page discovery reads. With all nine optional blocks switched on it is $0.0156 per lot, or $15.60 per 1,000 — and you only get there by ticking all nine yourself.

Measured on 20/08/2026, a run costs us $0.05 per 1,000 rows at worst — no proxy, no browser, no unblocker. The price is what keeps the Actor maintained, not what covers the traffic.

Free users

Apify free-plan runs are capped at 50 auctions per run. Everything else works the same: all 88 fields across the nine blocks, all 23 filters. Upgrade your Apify plan to lift the cap.

Run it

  1. Open the Actor in Apify Console and set a keyword, a category, a region, or any combination.
  2. Set maxItems to the number of lots you want, and tick any optional blocks you need under Optional data.
  3. Click Start, then export the dataset as CSV, JSON, Excel, or XML.

Or from the API:

curl -X POST "https://api.apify.com/v2/acts/parseforge~publicsurplus-scraper/runs?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"category":"motor pool","region":"Texas","onlyWithVin":true,"includeItemSpecs":true,"includeVinDecode":true,"maxItems":100}'

Use with AI agents (MCP)

The Actor is exposed over Apify's MCP server, so an agent can call it as a tool:

https://mcp.apify.com/sse?actors=parseforge/publicsurplus-scraper

Ask things like "find government pickup trucks on PublicSurplus in Texas closing today" and the agent fills the input itself.

Troubleshooting

No auctions came back.

The filters are ANDed. A keyword plus a category plus a region plus a bid-count floor can genuinely match nothing. Drop one filter at a time, and raise maxPages — a rare filter such as auctionTypes: ["dutch"] needs discovery to read deeper before it finds enough matches.

Fewer rows than maxItems.

maxItems is a ceiling. Discovery stops when the page budget is exhausted, and lots that closed between the listing page and the detail fetch are skipped. The log prints how many were filtered and how many had gone.

A keyword search returns things that do not look like the keyword.

PublicSurplus searches the full description, not just the title. A cabinet whose description says "bring a hand-truck" is a genuine hit for truck. Use titleExcludes to trim, or run includeDetails and filter the description yourself.

A column I expected is not in the output.

Most of the 88 fields belong to one of the nine optional blocks and are off until you tick them. bidCount needs includeBidding, vin needs includeItemSpecs, pickupZip needs includePickupLocation, and so on — the Optional data blocks table above maps every field to its checkbox. The filters keep working regardless, so onlyWithVin still finds the vehicles even with every block off.

Why is openingPrice missing on most rows?

PublicSurplus only labels the figure "Opening Price" while a lot has no bids; once someone bids it becomes "Current Price". About 18% of open lots are in that state. currentPrice is on every row either way.

Why is highBidder empty?

Nobody has bid yet. bidCount will be 0 on the same row.

Why are make, model and vin empty even with includeItemSpecs on?

Only lots where the agency filled in the vehicle form carry them — around 20% of all lots, and the large majority of Motor Pool and Heavy Equipment ones. Use onlyWithVin to keep just those; it works whether or not you bought the block.

A VIN did not decode.

NHTSA vPIC answers 200 with an error code for a VIN it cannot read, usually because the agency typed it wrong. The row keeps its vin and simply gets no vin* columns.

The run got slower or started failing.

PublicSurplus is a single application server and this Actor reads five pages at a time on purpose. If your IP gets rate-limited, switch proxyConfiguration on.

FAQ

QuestionAnswer
Do I need a PublicSurplus account or API key?No. PublicSurplus has no public API. This reads public auction pages only, so there is nothing to register or authenticate.
Will I be charged for data I did not ask for?No. Nine of the twelve events are optional blocks that are off by default; a run left alone bills result-item, listing-page and apify-actor-start and nothing else.
Can I filter on a column without paying for it?Yes. Filters run on the complete row, before the optional blocks are stripped. onlyWithVin, onlyWithBids, minBidCount, onlyWithImages and onlyWithAttachments all work with every block off.
Does it cover closed auctions and final sale prices?No. PublicSurplus puts closed lots behind a login, answering 401 to anonymous callers. This Actor returns open lots only.
Does it cover Canada?Yes. All 13 Canadian provinces and territories are in the region list, alongside 50 US states, DC and four US territories.
Can I fetch one specific lot?Yes. Put its URL or auction number in auctionUrls.
Can I follow one agency?Yes. Put its agencyId in agencyIds and the Actor walks its whole open catalogue.
How current is the data?Live. Every row is built from the page as it stands, and timeLeftSeconds is measured against PublicSurplus's own server clock.
How many lots are reachable?About 5,750 open site-wide, measured 20/08/2026, across roughly 230 pages of 25. A single search reaches all of them.
How many rows per run?Free plan: 50. Paid: up to 10,000, bounded by how many lots match your filters.
Does it bid for me?No. It reads public auction pages and never logs in, bids or transacts.
Does it need a proxy?No. It runs proxy-free by default.
Is this an official PublicSurplus product?No. It is unofficial and reads only publicly available PublicSurplus data.

Browse the full ParseForge collection for more scrapers.

🆘 Need help? Email parseforge@protonmail.com with your run ID, your input, and what you expected.

⚠️ Disclaimer. This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by PublicSurplus or The Public Group, LLC. It collects only publicly available auction data — lots that public agencies publish for anyone to browse — and no buyer accounts or personal profiles. highBidder is the masked handle PublicSurplus itself displays publicly and cannot be resolved to a person. You are responsible for using the data in compliance with PublicSurplus's terms and applicable laws.