# GovDeals Scraper — Surplus Auctions, Bids, VINs & Photos (`scrapelabmax/govdeals-scraper`) Actor

Scrape GovDeals government surplus auctions by keyword, category, state or URL. Current bids, bid counts, close times, location, seller, VIN, condition, meter and full photo galleries. Monitor mode for new lots. $0.75/1K.

- **URL**: https://apify.com/scrapelabmax/govdeals-scraper.md
- **Developed by:** [Scrapelab Max](https://apify.com/scrapelabmax) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 lots

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

## GovDeals Scraper — Surplus Auctions, Sold Prices, Fees, VINs & Photos

Extract government surplus auction lots from **[GovDeals](https://www.govdeals.com)** as clean JSON, CSV or Excel:

- **open auctions** you can bid on, or
- **sold lots with their final prices**, for pricing comparable items.

Search by keyword, category, state, ZIP radius, seller or sale type, or paste GovDeals search and lot URLs.
Optionally enrich every lot with:

- VIN, condition, meter reading and quantity;
- the **full photo gallery**;
- the **buyer's premium, fees and estimated total cost**;
- watcher count;
- payment, inspection and removal terms.

Schedule it with **monitor mode** to get only new lots, plus alerts when a bid changes.

**Cheapest full-featured GovDeals Actor:** **$0.75 per 1,000 lots**, or **$1.50 per 1,000** with full details. No
start fee beyond Apify's minimum. No proxies needed.

### What you get

| Group                         | Fields                                                                                                                                         |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Lot                           | `lotId`, `url`, `title`, `description`, `category`, `categoryCode`, `parentCategory`, `lotNumber`, `inventoryId`, `marketplace`                |
| Status & sale                 | `auctionStatus` (`active` / `sold`), `saleType` (Online Auction, Buy Now, Make Offer, Sealed Bid…), `buyNowPrice`, `audience`                  |
| Bidding                       | `currentBid` (final price when sold), `minimumBid`, `currency`, `bidCount`, `bidIncrement`, `hasReserve`, `reserveMet`                         |
| True cost (details)           | `buyerPremiumPercent`, `fees` (itemised), `feesTotal`, `estimatedTotalCost`                                                                    |
| Demand (details)              | `watcherCount`                                                                                                                                 |
| Timing                        | `auctionStartUtc`, `auctionEndUtc`, `secondsRemaining`, `isNewListing`                                                                         |
| Location                      | `address`, `city`, `state`, `zip`, `country`, `latitude`, `longitude`                                                                          |
| Seller                        | `sellerName`, `sellerAccountId`; opt-in `sellerContactName` / `Email` / `Phone` (only when GovDeals shows them publicly)                       |
| Vehicle & equipment (details) | `make`, `model`, `modelYear`, `vin`, `meterReading`, `meterUnit`, `condition`, `conditionCode`, `titleRestriction`                             |
| Terms & logistics (details)   | `quantity`, `quantityUnit`, `shippingAvailable`, `paymentInstructions`, `inspectionInstructions`, `removalInstructions`, `specialInstructions` |
| Photos                        | `photoUrl`, `photoUrls` (full gallery with details), `photoCount`, `photoUrlsText` (all URLs in one spreadsheet cell)                          |
| Monitoring                    | `changeType` (`new` / `bidChanged`), `previousBid`, `detailFetched`, `scrapedAt`                                                               |

Unknown values are always `null`. The Actor never guesses. Times are ISO-8601 UTC.

**Which fields you get depends on how you search.** GovDeals answers category/state/price browsing and keyword, ZIP or
sold searches with different engines:

| Search type                           | Bid count & minimum bid              | Description, address, coordinates |
| ------------------------------------- | ------------------------------------ | --------------------------------- |
| Browse open lots (no keyword, no ZIP) | ✅                                   | ✅                                |
| Keyword, ZIP radius or sold           | bid count only with `includeDetails` | only with `includeDetails`        |

Turn on `includeDetails` for complete rows.

### Export: JSON, CSV, Excel and more

Every run's results can be downloaded from the **Export** button or the Apify API as **JSON, CSV, Excel (XLSX), XML,
HTML or RSS**. They can also be sent to Google Sheets, Slack, email, Zapier, Make or a webhook through Apify integrations.

Ready-made table views give clean spreadsheet columns:

- **Lots**
- **Vehicles & equipment**
- **Sold results**
- **Costs & terms**

The run's **Output** tab links straight to each view, the full JSON and the run summary.

`photoUrlsText` keeps a whole gallery in one cell, so spreadsheets don't sprawl.

### Use cases

- **Resellers and flippers:** find underpriced equipment, vehicles, electronics and furniture near you, and compare
  against **what similar lots actually sold for**.
- **Dealers and exporters:** trucks, buses and heavy equipment with VINs, meter readings and condition.
- **True-cost bidding:** see the buyer's premium and fees before you bid.
- **Alerts:** schedule it hourly with monitor mode. New lots and bid changes go to Slack, email or Sheets.
- **Market research:** track sell-through prices by category, state, seller or sale type.

### Input examples

**Open pickups in Texas, ending within 48 hours**

```json
{ "searchTerms": ["pickup truck"], "states": ["TX"], "sortBy": "endingSoon", "endingWithinHours": 48, "maxItems": 200 }
```

**Sold prices: Ford F-150s sold in the last 30 days**

```json
{
  "auctionStatus": "sold",
  "soldWithinDays": 30,
  "searchTerms": ["ford f-150"],
  "includeDetails": true,
  "maxItems": 300
}
```

**Vehicles with full details and true cost**

```json
{ "searchTerms": ["chevrolet silverado"], "includeDetails": true, "maxItems": 500 }
```

**Buy Now and Make Offer lots from specific sellers**

```json
{ "saleTypes": ["buyNow", "makeOffer"], "sellerAccountIds": [29908, 1147], "maxItems": 500 }
```

**Paste GovDeals search or lot URLs**

```json
{
  "startUrls": [
    { "url": "https://www.govdeals.com/en/search?kWord=laptop" },
    { "url": "https://www.govdeals.com/asset/10/29908" }
  ],
  "includeDetails": true
}
```

**New lots + bid-change alerts (schedule this run)**

```json
{ "searchTerms": ["forklift"], "onlyNewSinceLastRun": true, "alertOnBidChange": true, "maxItems": 1000 }
```

`maxItems` is the total across all your search terms and URLs, which run in order.

### Pricing

Pay per result. You only pay for lots delivered to your dataset.

| Event                                                                      | Price                            |
| -------------------------------------------------------------------------- | -------------------------------- |
| Lot (list data)                                                            | $0.00075 ($0.75 / 1,000)         |
| Lot details (VIN, gallery, condition, fees & total cost, watchers, terms…) | +$0.00075 ($1.50 / 1,000 all-in) |
| Actor start (once per run)                                                 | $0.00005                         |

Set **Maximum cost per run** in the run options and the Actor stops cleanly when that budget is reached.

### Sold mode

`auctionStatus: "sold"` returns closed lots (`auctionStatus: "sold"`), and `currentBid` is the final price. Results
come most recently closed first and go back about a year.

- **`soldWithinDays` narrows the window.** 7, 30 and 60 days are filtered on GovDeals' side; any other value is cut
  exactly on our side.
- **All the usual filters still apply:** keyword, category, state, ZIP, price, seller and sale type.

### Buyer's premium and fees

With `includeDetails`, open lots get:

- `buyerPremiumPercent`;
- itemised `fees`;
- `estimatedTotalCost` (current bid + premium + fees, excluding tax and shipping).

Most GovDeals government sellers charge no buyer's premium, so expect `0` there. Fees mainly appear on AllSurplus
dealer lots (for example a $299 doc fee).

### Monitor mode

With `onlyNewSinceLastRun`, the Actor remembers lots it already returned for the **same search and filters** (named
key-value store `govdeals-monitor`) and only returns new ones (`changeType: "new"`). A lot is forgotten after 60 days
without being seen, and changing the search starts fresh.

Add `alertOnBidChange` to also get previously returned lots whose current bid moved since the last run
(`changeType: "bidChanged"`, with `previousBid`).

### Run summary

Each run writes `RUN_SUMMARY` to its key-value store with:

- matches per query;
- pages fetched;
- lots emitted, duplicates, filtered and previously seen;
- detail, bid-count, fee and watcher-count errors;
- bid-change alerts emitted;
- why the run stopped.

### How it works / responsible use

The Actor reads the same public JSON the GovDeals website loads for any logged-out visitor:

- no login, cookies or captcha solving;
- one request at a time with polite delays, and it backs off when asked;
- it never returns bidder identities;
- seller points of contact are returned only if you turn on `includeSellerContact`, and only when GovDeals itself
  displays them publicly on the listing.

You are responsible for using the data in line with GovDeals' terms and applicable law.

### FAQ

**Why are some fields null?** GovDeals doesn't publish them for that lot (e.g. no VIN for furniture), or they come
only from the detail page and `includeDetails` is off.

**How far back do sold prices go?** About 12 months.

**Does it cover AllSurplus lots?** GovDeals search includes some AllSurplus (`marketplace: "AD"`) and Network
International (`"NI"`) lots. They are returned with their own listing URL.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords to search for, e.g. <code>truck</code>, <code>laptop</code>, <code>bucket truck</code>. Each term runs as its own search; results are de-duplicated across terms. Leave empty (with no start URLs) to browse every active lot.

## `startUrls` (type: `array`):

Paste search, category or location pages from www.govdeals.com, e.g. <code>https://www.govdeals.com/en/search?kWord=truck</code>, <code>https://www.govdeals.com/en/bucket-trucks</code> or <code>https://www.govdeals.com/en/texas</code>. Keyword, category, state, ZIP + miles, price and sort in the URL are applied. You can also paste single lots, e.g. <code>https://www.govdeals.com/asset/10/29908</code> (AllSurplus lot URLs work too) to track exactly those lots. The filters below are applied on top.

## `categoryIds` (type: `array`):

GovDeals category codes or category URL slugs, e.g. <code>644</code> or <code>bucket-trucks</code> (Bucket Trucks), <code>94C</code> or <code>trucks</code> (all trucks). Lots matching any listed category are returned.

## `auctionStatus` (type: `string`):

<b>Active</b>: lots open for bidding now. <b>Sold</b>: lots that already closed (about the last 12 months GovDeals keeps), with the final price in <code>currentBid</code> — ideal for price research and comps. In sold mode the closing-time and new-listing filters do not apply.

## `soldWithinDays` (type: `integer`):

Sold mode only: lots that closed within this many days of the run start, e.g. <code>7</code> or <code>30</code>. Leave empty for everything GovDeals still shows (about 12 months).

## `saleTypes` (type: `array`):

Only lots sold this way. Leave empty for every sale type. Each selected type runs as its own search.

## `sellerAccountIds` (type: `array`):

Only lots from these GovDeals sellers (agencies). The seller account ID is the last number in a lot URL: <code>https://www.govdeals.com/asset/10/<b>29908</b></code>. Leave empty for all sellers.

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

Only lots located in these US states or Canadian provinces. Leave empty for all locations.

## `zipCode` (type: `string`):

Only lots near this 5-digit US ZIP code or Canadian postal code (e.g. <code>77002</code>, <code>M5V 3L9</code>). Uses the radius below (50 miles if not set).

## `radiusMiles` (type: `integer`):

Search radius around the ZIP / postal code. Requires a ZIP / postal code.

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

Only lots whose current bid / price (final price for sold lots) is at least this amount, in the lot’s currency. Lots without a price are excluded when a price filter is set.

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

Only lots whose current bid / price (final price for sold lots) is at most this amount, in the lot’s currency.

## `endingWithinHours` (type: `integer`):

Active lots only: auctions that close within this many hours of the run start, e.g. <code>24</code> for lots closing today.

## `newListingsOnly` (type: `boolean`):

Active lots only: lots GovDeals marks as newly listed.

## `sortBy` (type: `string`):

Order in which lots are collected — matters when <b>Max lots</b> cuts the list short. For sold lots, <b>Best match</b> and <b>Closing soonest</b> both mean most recently closed first, and the price sorts use the final price.

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

Stop after this many lots in total across all searches. You are only charged for lots returned.

## `includeDetails` (type: `boolean`):

Also open each lot to add VIN / serial, condition, meter reading, quantity, full photo gallery, shipping and removal instructions, and title restrictions. Slower and billed as an extra per-lot event.

## `includeSellerContact` (type: `boolean`):

Add the seller’s point of contact (name, email, phone) when GovDeals shows it publicly on the lot page. Requires <b>Include lot details</b>.

## `onlyNewSinceLastRun` (type: `boolean`):

Monitoring mode: skip lots this Actor (or this saved task) already returned in an earlier run. Ideal for scheduled runs that alert on new inventory.

## `alertOnBidChange` (type: `boolean`):

Monitoring mode add-on: also return lots seen in an earlier run whose current bid has changed since, with the previous bid in <code>previousBid</code>. Requires <b>Only lots not seen in previous runs</b>.

## Actor input object example

```json
{
  "searchTerms": [
    "truck"
  ],
  "startUrls": [],
  "categoryIds": [],
  "auctionStatus": "active",
  "saleTypes": [],
  "sellerAccountIds": [],
  "states": [],
  "newListingsOnly": false,
  "sortBy": "relevance",
  "maxItems": 100,
  "includeDetails": false,
  "includeSellerContact": false,
  "onlyNewSinceLastRun": false,
  "alertOnBidChange": false
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `vehicles` (type: `string`):

No description

## `sold` (type: `string`):

No description

## `costs` (type: `string`):

No description

## `allFields` (type: `string`):

No description

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "truck"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapelabmax/govdeals-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 = {
    "searchTerms": ["truck"],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapelabmax/govdeals-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 '{
  "searchTerms": [
    "truck"
  ],
  "maxItems": 100
}' |
apify call scrapelabmax/govdeals-scraper --silent --output-dataset

```

## MCP server setup

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