# CaleProcure Solicitations Scraper (`automation-lab/cal-eprocure-solicitations-contracts`) Actor

Search and export current California CaleProcure solicitations with event IDs, agencies, statuses, and bid deadlines.

- **URL**: https://apify.com/automation-lab/cal-eprocure-solicitations-contracts.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## CaleProcure Solicitations Scraper

Monitor current California public bid opportunities from the official CaleProcure California State Contracts Register.

The Actor exports useful solicitation rows with event IDs, titles, issuing departments, statuses, and normalized bid deadlines.
It is designed for government-sales teams that need a repeatable feed rather than manual portal checks.

### What does the CaleProcure scraper do?

The Actor opens the public CaleProcure event search, reads current posted opportunities, applies your filters, and saves matching records to an Apify dataset.

Use it to:

- find California solicitations by keyword;
- monitor one state department or agency;
- look up a known event ID;
- focus on a deadline window;
- schedule recurring opportunity checks;
- export results as JSON, CSV, Excel, XML, or RSS through Apify.

The Actor does not log in, submit bids, or access private vendor-account data.

### Who is this Actor for?

- **Government contractors** building a California opportunity pipeline.
- **Business-development teams** monitoring target agencies.
- **Bid managers** tracking closing dates and event identifiers.
- **Market researchers** comparing public purchasing demand across departments.
- **Data engineers** feeding public solicitation rows into a CRM, warehouse, or alerting workflow.

### Why use this Actor?

CaleProcure is an interactive InFlight/PeopleSoft portal.
The results are rendered after browser and session initialization rather than exposed as a simple static page.

This Actor provides:

- one normalized record per solicitation;
- case-insensitive keyword, event, and agency filters;
- normalized `YYYY-MM-DD` deadline dates;
- bounded proxy-session rotation when the portal rejects an edge IP;
- a stable default-dataset contract for Apify integrations;
- pay-per-result billing rather than a subscription.

### What CaleProcure data is extracted?

| Field | Meaning |
| --- | --- |
| `eventId` | Public CaleProcure event or solicitation identifier |
| `eventName` | Public event title |
| `department` | Issuing California department or agency |
| `deadline` | Deadline text exactly as displayed by the portal |
| `deadlineDate` | Normalized date in `YYYY-MM-DD`, or `null` when unavailable |
| `deadlineTime` | Displayed time and timezone, or `null` when unavailable |
| `status` | Current status displayed in the event search |
| `sourceUrl` | Official source search page |
| `scrapedAt` | ISO 8601 extraction timestamp |

### Getting started

1. Open the Actor input page.
2. Enter a keyword, event ID, department, or deadline window.
3. Choose the maximum number of matching results.
4. Keep the default Apify Proxy setting enabled.
5. Click **Start**.
6. Open the **Dataset** tab when the run finishes.
7. Export or connect the dataset to your downstream system.

For a broad current feed, leave all text and date filters empty.

### Input parameters

| Input | Type | Default | Description |
| --- | --- | --- | --- |
| `keyword` | string | empty | Match text in the event ID or event name |
| `eventId` | string | empty | Match a known event identifier or identifier fragment |
| `department` | string | empty | Match issuing department or agency text |
| `endDateFrom` | string | empty | Keep deadlines on or after `YYYY-MM-DD` |
| `endDateTo` | string | empty | Keep deadlines on or before `YYYY-MM-DD` |
| `maxItems` | integer | `20` | Save at most 1–1,000 matching records |
| `proxyConfiguration` | object | Apify Proxy | Proxy configuration used for the portal session |

All text matching is case-insensitive.
Date filters are applied to normalized deadline dates.
`endDateFrom` must not be later than `endDateTo`.

### Input examples

Find software solicitations:

```json
{
  "keyword": "software",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

Monitor Caltrans opportunities:

```json
{
  "department": "Department of Transportation",
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

Build a larger services pipeline:

```json
{
  "keyword": "services",
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### Output example

A real current result has this shape:

```json
{
  "eventId": "09A1149",
  "eventName": "Trash Collection, Hauling, and Disposal Services in Inyo County.",
  "department": "Department of Transportation",
  "deadline": "08/13/2026 2:00PM PDT",
  "deadlineDate": "2026-08-13",
  "deadlineTime": "2:00PM PDT",
  "status": "Posted",
  "sourceUrl": "https://caleprocure.ca.gov/pages/Events-BS3/event-search.aspx",
  "scrapedAt": "2026-08-13T20:24:34.797Z"
}
```

Source data changes as agencies post and close events.
Use event IDs as stable business keys where practical.

### How much does it cost to monitor California bid opportunities?

The Actor charges one **Run started** event of **$0.01** per run and one **Item extracted** event for each saved record.
The current BRONZE item price is **$0.0524** and higher-volume account tiers are cheaper.

Illustrative BRONZE totals:

| Saved records | BRONZE price calculation |
| ---: | --- |
| 10 | 0.01 + 10 × 0.0524 = 0.534 USD |
| 100 | 0.01 + 100 × 0.0524 = 5.250 USD |
| 1,000 | 0.01 + 1,000 × 0.0524 = 52.410 USD |

No-result runs pay only the Start event.
Actual platform compute and proxy usage are handled by Apify under the active pricing configuration.
Always check the live pricing panel for the tier applicable to your account.

### Scheduling bid monitoring

Use an Apify schedule to run the same input daily or weekly.
A typical monitoring workflow is:

1. Run the Actor with an agency or keyword filter.
2. Store `eventId` values in your CRM or database.
3. Compare the latest dataset with the previous run.
4. Alert only on newly observed IDs or changed deadlines.
5. Route qualified opportunities to a bid owner.

The Actor itself returns the current snapshot; it does not send alerts or maintain change history.

### Export and integration workflows

From the dataset you can:

- download CSV or Excel for bid review;
- send rows to Google Sheets;
- trigger a webhook when a run completes;
- load JSON into Snowflake, BigQuery, or a relational database;
- connect through Make or Zapier;
- use event IDs to deduplicate scheduled snapshots;
- join department names with an internal account-owner list.

### Run with the Apify API using cURL

Replace `YOUR_TOKEN` with an Apify API token:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~cal-eprocure-solicitations-contracts/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "keyword": "software",
    "maxItems": 20,
    "proxyConfiguration": {"useApifyProxy": true}
  }'
```

The response includes the run ID and default dataset ID.

### Run with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor(
  'automation-lab/cal-eprocure-solicitations-contracts',
).call({
  department: 'Department of Transportation',
  maxItems: 25,
  proxyConfiguration: { useApifyProxy: true },
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Run with Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor(
    "automation-lab/cal-eprocure-solicitations-contracts"
).call(run_input={
    "keyword": "services",
    "maxItems": 50,
    "proxyConfiguration": {"useApifyProxy": True},
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### Use through Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/cal-eprocure-solicitations-contracts"
```

#### Claude Desktop, Cursor, and VS Code MCP setup

Claude Desktop, Cursor, and VS Code can use this HTTP MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/cal-eprocure-solicitations-contracts"
    }
  }
}
```

Example prompts:

- “Find current California software solicitations and summarize their deadlines.”
- “Export 25 current Department of Transportation opportunities.”
- “Create a table of California service bids grouped by issuing agency.”

### Reliability and proxy behavior

CaleProcure can reject individual network edge sessions with HTTP 403.
The Actor uses a coherent browser, cookies, user agent, and proxy identity for each attempt.
It retires a rejected identity and retries with a bounded new session.

The default datacenter proxy path was verified.
A residential fallback is not enabled because it did not improve access and would add unmeasured cost.
Do not disable the proxy unless you have independently verified that your execution network reaches the portal.

### Limits

- The Actor currently extracts posted rows shown by the public event search.
- It does not claim complete historical or award coverage.
- It does not open attachments or submit responses.
- It does not extract private vendor-account fields.
- Filters operate on the fields available in the current results table.
- Department spelling follows the source and may contain abbreviations.
- CaleProcure can change its InFlight/PeopleSoft markup without notice.
- Naturally empty filters return a successful run with zero saved items.
- Portal outages and repeated session rejection cause a failed run rather than a misleading empty dataset.

### Tips for useful results

- Start with a short keyword such as `software`, `security`, or `services`.
- Use the exact visible department name for a narrow agency feed.
- Keep `maxItems` small while testing a new workflow.
- Use both deadline inputs for a bounded bid-planning window.
- Deduplicate recurring snapshots by `eventId`.
- Preserve `deadline` when the exact displayed timezone matters.
- Use `deadlineDate` for sorting and warehouse filters.

### Legality and responsible use

This Actor accesses public procurement information without logging in.
You are responsible for complying with applicable laws, portal terms, procurement rules, and your organization's data policies.

Do not use the data to overload the source, misrepresent eligibility, automate prohibited bid actions, or infer sensitive information.
Verify deadlines and requirements on the official solicitation before making a business decision.
This Actor is not affiliated with the State of California, FI$Cal, DGS, or CaleProcure.

### Troubleshooting

#### Why did my run return zero records?

Your filters may not match the current posted snapshot.
Remove filters, reduce the keyword to a shorter phrase, or verify the department spelling.
A genuine no-match run logs the number of source rows inspected.

#### Why did the run fail with a CaleProcure access error?

The portal may have rejected several edge sessions or may be temporarily unavailable.
Keep the default proxy enabled and retry later with the same input.
The Actor fails explicitly after bounded retries instead of returning false empty output.

#### Why is a deadline field null?

`deadlineDate` or `deadlineTime` is null only when the source text cannot be normalized safely.
The original `deadline` value remains available for inspection.

#### Can I scrape more than 1,000 records?

The current input cap is 1,000 matching rows per run.
The live posted register is usually smaller.
Use scheduled snapshots rather than aggressive repeated runs.

### FAQ

#### Does this Actor require a CaleProcure login?

No. It uses the public California State Contracts Register event search.

#### Can it monitor one agency?

Yes. Set `department` to a distinctive full or partial agency name.

#### Can it find one event?

Yes. Set `eventId` to the full ID or a distinctive ID fragment.

#### Does it include closed contracts and awards?

Not as a guaranteed product scope.
The current implementation targets posted opportunities visible in the public search.

#### Does it download bid documents?

No. Attachments and bid-response actions are outside this Actor's scope.

#### Can I schedule it?

Yes. Apify schedules can run any saved input at your chosen interval.

#### How fresh is the data?

Each run reads the portal's current rendered listing at run time.
The Actor does not control when agencies update CaleProcure.

### Related Actors

For a broader government-procurement workflow, combine this Actor with:

- [SAM.gov Government Contracts Scraper](https://apify.com/automation-lab/samgov-government-contracts-scraper) for US federal opportunities.
- [New York State Contract Reporter Scraper](https://apify.com/automation-lab/new-york-state-contract-reporter-scraper) for another state-level procurement feed.
- [AusTender Current Tender Opportunities Scraper](https://apify.com/automation-lab/austender-current-tender-opportunities-scraper) for Australian federal opportunities.

Keep source-specific event IDs separate when combining datasets.

# Actor input Schema

## `keyword` (type: `string`):

Keep solicitations whose event ID or event name contains this text (case-insensitive). Leave empty for all posted opportunities.

## `eventId` (type: `string`):

Keep solicitations whose CaleProcure event ID contains this value.

## `department` (type: `string`):

Keep solicitations whose issuing department contains this text, for example Department of Transportation.

## `endDateFrom` (type: `string`):

Keep opportunities closing on or after this date (YYYY-MM-DD).

## `endDateTo` (type: `string`):

Keep opportunities closing on or before this date (YYYY-MM-DD).

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

Maximum number of matching solicitation records to save.

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

Proxy settings used to reach CaleProcure reliably. The default Apify Proxy configuration is recommended.

## Actor input object example

```json
{
  "keyword": "software",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Current CaleProcure solicitation records matching the input filters.

# 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 = {
    "keyword": "software",
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/cal-eprocure-solicitations-contracts").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 = {
    "keyword": "software",
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/cal-eprocure-solicitations-contracts").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 '{
  "keyword": "software",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call automation-lab/cal-eprocure-solicitations-contracts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/cal-eprocure-solicitations-contracts"
        }
    }
}

```

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/z6bQGl8Thofw3RIXX/builds/uDlrXXJbhial5uBzT/openapi.json
