# AusTender Contract Notices Scraper (Australian Government) (`lafabbricallc/australia-austender-contract-notices`) Actor

Australian Government contract notices from the official AusTender OCDS API as flat rows: agency, supplier, value, UNSPSC category, procurement method, dates, notice URL. Filter by date, keyword, agency, supplier, category, value. No contact details, no personal data.

- **URL**: https://apify.com/lafabbricallc/australia-austender-contract-notices.md
- **Developed by:** [La Fabbrica LLC](https://apify.com/lafabbricallc) (community)
- **Categories:** Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 contract notices

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

### What does AusTender Contract Notices Scraper do?

AusTender Contract Notices Scraper turns the Australian Government's procurement register, **AusTender** (tenders.gov.au), into flat, spreadsheet-ready rows: one row per **contract notice** with the procuring agency, the supplier organisation and its ABN, contract value in AUD, UNSPSC category, procurement method (open or limited tender, with the CPR condition or exemption used), signing date, contract period, status and the public notice URL. It reads AusTender's own **OCDS open-data API** (`api.tenders.gov.au/ocds`), so there is no HTML parsing to break and 100 notices arrive per request.

Pick a published-date window (default: the last three days) and optional filters, and you get for example:

- every contract the Department of **Defence** signed this week, without amendments,
- every **IT or consulting** contract (UNSPSC segments 43 and 81) above A$100,000 in the last month,
- every notice won by a **named supplier** (`"suppliers": ["Datacom"]`), or every **limited tender** citing a particular CPR condition,
- specific notices by id (`"contractNoticeIds": ["CN4277105"]`), including their amendment history.

The actor runs with Apify's **limited permissions** level: it can only read and write its own run storages and never touches other data in your account. It does **not** log in and does **not** collect personal data: agency and supplier **contact officers (names, e-mails, phone numbers) and street addresses are never read**, and when the supplier is a natural person (a sole trader listed as `SURNAME, GIVEN NAMES`, `Given Surname`, initials plus surname, or a trading name containing a personal name) the name is replaced by `[individual supplier, name withheld]` with `supplierType: "individual"`, `personalDataRedacted: true` and the ABN, suburb and postcode set to `null`. Only Contract Notices are read; Approach-to-Market material, which AusTender does not license for redistribution, is never requested.

### Why use it?

- **Bid and sales teams**: a daily CSV of who won what, at which agency, for how much, to spot incumbents, panel usage and contract end dates (renewal windows) in your category.
- **Market and competitor analysis**: total contract value by supplier, agency or UNSPSC segment over any window up to 92 days per run; chain runs for longer histories.
- **Journalists, researchers and civic-tech**: limited-tender share, exemption codes and value distributions straight from the official register, with the licence attribution already in each row.
- **AI agents and RAG**: "Which cyber-security contracts did Home Affairs sign this month?" becomes one actor call with `agencies`, `keywords` and `daysBack`.

On Apify you also get scheduling, webhooks, run monitoring and integrations (Google Sheets, Make, Zapier, LangChain, MCP).

### How to use it

On the actor page, open the **Input** tab, set a date window and any filters, and click **Start**. Leave every field at its default to get the newest 100 notices from the last three days. The fields:

| Field | Type | Default | Meaning |
|---|---|---|---|
| `daysBack` | integer 1-92 | `3` | Read notices published in the last N days (UTC) when `dateFrom` is empty |
| `dateFrom`, `dateTo` | `YYYY-MM-DD` | none / today | Explicit published-date window, at most 92 days per run |
| `keywords` | array | none | Keep notices whose title, description, agency, supplier, UNSPSC code or CN id contains any of these (case-insensitive substring) |
| `excludeKeywords` | array | none | Drop notices containing any of these |
| `agencies` | array | none | Keep notices whose agency name contains any of these |
| `suppliers` | array | none | Keep notices whose supplier name contains any of these |
| `unspscPrefixes` | array | none | Keep notices whose UNSPSC code starts with any of these (`"43"` IT, `"8010"` management advisory, `"80111600"` temporary personnel) |
| `procurementMethod` | `any` / `open` / `limited` / `selective` | `any` | Filter by procurement method |
| `minValueAud`, `maxValueAud` | number | none | Contract value range in Australian dollars |
| `includeAmendments` | boolean | `true` | Also return amendment releases (`releaseTag: "contractAmendment"`) |
| `contractNoticeIds` | array | none | Fetch these CN ids directly instead of a date window (up to 200 per run) |
| `maxItems` | integer | `100` | Stop after this many rows (max 20,000) |

All filters combine with AND; each list matches when any of its entries matches. Notices are published on Canberra business days; a weekend window can legitimately be empty, and the log tells you which filter to loosen when nothing matches.

#### Example input

IT and consulting contracts above A$100,000 from the last week:

```json
{
    "daysBack": 7,
    "unspscPrefixes": ["43", "81"],
    "minValueAud": 100000,
    "maxItems": 500
}
```

Defence contracts signed in a date range, original notices only:

```json
{
    "dateFrom": "2026-09-15",
    "dateTo": "2026-09-22",
    "agencies": ["Defence"],
    "includeAmendments": false,
    "maxItems": 1000
}
```

Specific notices by id:

```json
{
    "contractNoticeIds": ["CN4277105", "CN4278153"]
}
```

### Example output

One row per contract notice. Download it as JSON, CSV or Excel, or read it through the API.

```json
{
    "contractNoticeId": "CN4277105",
    "ocid": "prod-ea3c950e489c4664946de71bc37b0985",
    "releaseId": "prod-ea3c950e489c4664946de71bc37b0985-cfe2d71678833e338f8911ad5075e77a",
    "releaseTag": "contract",
    "amendmentId": null,
    "amendsReleaseId": null,
    "publishedAt": "2026-09-22T23:50:26Z",
    "title": null,
    "description": "Provision of Delivery Confidence Assessment Services.",
    "agency": "Australian Energy Regulator",
    "agencyAbn": "18105599265",
    "supplier": "ServeGate Australia",
    "supplierAbn": "56609386156",
    "supplierType": "organisation",
    "supplierLocality": "Canberra",
    "supplierRegion": "ACT",
    "supplierPostcode": "2601",
    "supplierCountry": "AUSTRALIA",
    "personalDataRedacted": false,
    "unspscCode": "80101507",
    "procurementMethod": "open",
    "procurementMethodDetails": "Open tender",
    "limitedTenderExempt": null,
    "limitedTenderReasonCode": null,
    "limitedTenderReason": null,
    "exemptionCode": null,
    "exemption": null,
    "valueAud": 35000,
    "currency": "AUD",
    "dateSigned": "2026-09-22T23:50:26Z",
    "startDate": "2026-09-13T14:00:00Z",
    "endDate": "2027-09-12T14:00:00Z",
    "status": "active",
    "noticeUrl": "https://www.tenders.gov.au/Cn/Show/CN4277105",
    "apiUrl": "https://api.tenders.gov.au/ocds/findById/CN4277105",
    "source": "AusTender (Australian Government Department of Finance)",
    "license": "CC BY 3.0 AU (https://creativecommons.org/licenses/by/3.0/au/)",
    "retrievedAt": "2026-09-27T03:15:17.651Z"
}
```

The **Output** tab shows a table view with the most useful columns; the run's key-value store holds a `SUMMARY` record with counts (read, matched, saved, sole-trader names withheld, pages read, ids not found).

### Limits

- At most 92 days per run and 20,000 rows per run; run several windows for longer histories. A busy day has roughly 100-400 notices.
- Contract Notices and their amendments only. Approach-to-Market (ATM) and Standing Offer notices are not returned.
- Supplier names that look like a natural person are withheld (see above); `supplierRegion` and `supplierCountry` are kept for them because a state is not personal data. Typically 5-10% of notices go to individuals (contractors, barristers, landlords). The detection is deliberately cautious: a few firms named after their founders (two or three plain words, no entity suffix or business noun, for example a law partnership) are withheld too, roughly 1-2% of rows. If you find a personal name that slipped through, open an issue and it will be excluded.
- Values are as published by the agency (GST inclusive); `valueAud` is `null` on the rare notices without an amount.
- The API is the Department of Finance's; when it is down the actor retries four times with back-off and then fails with the HTTP status in the message.

### Data source and licence

Data comes from the AusTender OCDS API published by the Australian Government Department of Finance. Contract Notice data is licensed under [Creative Commons Attribution 3.0 Australia](https://creativecommons.org/licenses/by/3.0/au/); every row carries `source` and `license` fields so you can keep the attribution when you republish. The actor sends one request per 100 notices with an identifying User-Agent and no concurrency.

### How much does it cost?

This actor uses **pay-per-event** pricing. You pay two things and nothing else:

| Event | Price | When |
|---|---|---|
| Actor start | $0.02 | Once per run, after your input is validated |
| Contract notice | $0.003 | Once per row saved to the dataset |

A typical run of 100 notices costs **$0.32**; a full week of every notice (about 900 rows) about **$2.72**. Set **Maximum cost per run** in the run options to cap spending; the actor stops cleanly when the cap is reached and you keep everything saved up to that point. Free-plan users can try it within their monthly platform credit.

### FAQ

**Why is `title` often empty or a bare number?** Agencies fill the title inconsistently; `description` is the reliable text field.

**Why do I get two rows for one CN id?** The original notice and each amendment are separate releases. Set `includeAmendments: false` to keep only originals, or group by `contractNoticeId`.

**Can I get the contact officer for a notice?** No. Contact names, e-mails and phone numbers are personal data and are never read by this actor. The `noticeUrl` opens the public notice page where the agency lists its enquiries channel.

**Does it scrape the tenders.gov.au website?** No. It reads only the official JSON API, respecting the site's robots rules, and never logs in.

# Actor input Schema

## `daysBack` (type: `integer`):

How many days of published notices to read, counting back from "Date to" (or today, UTC) when "Date from" is empty. 1-92.

## `dateFrom` (type: `string`):

First published date to include, YYYY-MM-DD (UTC). Leave empty to use "Days back".

## `dateTo` (type: `string`):

Last published date to include, YYYY-MM-DD (UTC). Leave empty for today. At most 92 days between "Date from" and "Date to".

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

Keep notices whose title, description, agency, supplier, UNSPSC code or CN id contains any of these words (case-insensitive substring). Empty = keep everything.

## `excludeKeywords` (type: `array`):

Drop notices whose title, description, agency, supplier, UNSPSC code or CN id contains any of these words.

## `agencies` (type: `array`):

Keep notices whose procuring agency name contains any of these, for example \["Defence", "Services Australia"].

## `suppliers` (type: `array`):

Keep notices whose supplier (organisation) name contains any of these, for example \["Accenture", "Datacom"].

## `unspscPrefixes` (type: `array`):

Keep notices whose UNSPSC category code starts with any of these, for example \["43"] for IT hardware and software, \["8010"] for management advisory services, \["80111600"] for temporary personnel.

## `procurementMethod` (type: `string`):

"open" = open tender, "limited" = limited tender (single or few suppliers approached), "selective" = prequalified panel or selective tender, "any" = no filter.

## `minValueAud` (type: `integer`):

Keep notices with a contract value at or above this amount in Australian dollars.

## `maxValueAud` (type: `integer`):

Keep notices with a contract value at or below this amount in Australian dollars.

## `includeAmendments` (type: `boolean`):

Contract notice amendments (variations, extensions) are published as separate releases with "releaseTag": "contractAmendment". Turn off to keep only original notices.

## `contractNoticeIds` (type: `array`):

Fetch these specific notices instead of a date window, for example \["CN4277105", "CN4278153"]. Up to 200 per run. Filters still apply.

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

Stop after this many notices have been saved. You are charged only for notices actually saved. 1-20000.

## Actor input object example

```json
{
  "daysBack": 3,
  "keywords": [],
  "excludeKeywords": [],
  "agencies": [],
  "suppliers": [],
  "unspscPrefixes": [],
  "procurementMethod": "any",
  "includeAmendments": true,
  "contractNoticeIds": [],
  "maxItems": 100
}
```

# Actor output Schema

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

No description

## `itemsCsv` (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 = {
    "daysBack": 3,
    "keywords": [],
    "excludeKeywords": [],
    "agencies": [],
    "suppliers": [],
    "unspscPrefixes": [],
    "contractNoticeIds": [],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("lafabbricallc/australia-austender-contract-notices").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 = {
    "daysBack": 3,
    "keywords": [],
    "excludeKeywords": [],
    "agencies": [],
    "suppliers": [],
    "unspscPrefixes": [],
    "contractNoticeIds": [],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("lafabbricallc/australia-austender-contract-notices").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 '{
  "daysBack": 3,
  "keywords": [],
  "excludeKeywords": [],
  "agencies": [],
  "suppliers": [],
  "unspscPrefixes": [],
  "contractNoticeIds": [],
  "maxItems": 100
}' |
apify call lafabbricallc/australia-austender-contract-notices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lafabbricallc/australia-austender-contract-notices"
        }
    }
}
```

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/RVl0JVUzQjBAr4whp/builds/bzFgbua4TLjU6QnoR/openapi.json
