# Web3 Audit Contest Aggregator (`tactful_anvil/web3-audit-contest-aggregator`) Actor

Every Web3 audit contest in one run: Code4rena, Sherlock, CodeHawks and Cantina. Prize pool in USD, start/end dates, days left, public/private/invite-only access, KYC flags and an opportunity score. HTTP-only, no login.

- **URL**: https://apify.com/tactful\_anvil/web3-audit-contest-aggregator.md
- **Developed by:** [Mr Zack](https://apify.com/tactful_anvil) (community)
- **Categories:** Developer tools, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.95 / 1,000 contest results

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/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

## Web3 Audit Contest Aggregator — Code4rena, Sherlock, CodeHawks & Cantina

Security researchers pick their next audit contest by opening four sites, four sort orders and four vocabularies — every week, because the boards rot fast: contests launch, close and hit judging on a weekly cycle.

**One run of this Actor returns every audit contest from Code4rena, Sherlock, CodeHawks and Cantina in a single normalized schema**: prize pool converted to USD, start and end dates with days-remaining, public / private / invite-only access, KYC flags where the platform publishes them, and a 0-100 opportunity score you can sort by.

No login, no API key, no browser, no residential proxy. HTTP-only, so runs finish in seconds.

### Who is this for?

- **Security researchers & audit contest hunters** — stop tab-hopping. One table: what is live, what it pays in USD, how many days you have left, and whether you can actually join (public vs invite-only, KYC or not).
- **Researchers planning their month** — `statuses: ["upcoming"]`, sorted by `startingSoon`, is your calendar.
- **Security firms & protocols** — benchmark prize pools across all four platforms before booking your own contest.
- **Analysts & builders** — the competitive-audit market as one dataset: ~540 contests of history across four platforms for prize-inflation and platform-share analysis.
- **AI agents (MCP)** — pay-per-event Actors are callable as tools. *"Which live audit contest pays the most and doesn't require KYC?"* becomes one tool call.

### What one row looks like

| Field | Example | Notes |
| --- | --- | --- |
| `platform` / `source` | `Code4rena` / `code4rena` | also Sherlock, CodeHawks, Cantina |
| `title`, `organizer` | `K2`, `Starknet` | anonymized private contests keep `title: null` — never fabricated |
| `status` | `live` | canonical, derived from the clock: `upcoming` / `live` / `judging` / `ended`. The platform's own label stays in `statusRaw` |
| `prizePoolUsd` | `135000` | stablecoin pools convert 1:1; a 7.25 ETH pool without a published rate stays `null` rather than a made-up number (`prizeRaw` keeps the original string) |
| `startsAt`, `endsAt`, `daysUntilEnd`, `daysUntilStart`, `durationDays` | | deadline math done for you |
| `accessType` | `public` | `private` and `invite-only` contests are flagged, filter with `publicOnly` |
| `kycRequired` | `false` | published by CodeHawks and Cantina; `null` where a platform doesn't say |
| `tags` | `["Stellar", "Audit"]` | chains, languages, platform labels |
| `nsloc` | `1250` | scope size, CodeHawks only |
| `opportunityScore` | `72.4` | see below |
| `url` | direct link | jump straight to the contest |

Any field a platform does not publish comes back `null` — never a fabricated zero.

#### How the opportunity score works

Deliberately simple, documented, reproducible — so you can argue with it:

- **55% prize size** — log-scaled from $1k to $1M, because contest pools span three orders of magnitude and a linear scale would flatten everything under $100k.
- **30% timing** — a live contest with 3+ days left scores full marks; one draining tonight scores low; far-future contests score lower than ones starting this week.
- **15% access** — public > invite-only > private.

Ended and judging contests score `null` (nothing left to compete for). Unknown prize = `null` score, not a flattering guess.

### Input examples

The actionable board (default): everything live or upcoming, best first —

```json
{ "statuses": ["live", "upcoming"], "sortBy": "opportunity" }
```

The no-KYC, joinable-today board:

```json
{ "statuses": ["live"], "publicOnly": true, "excludeKyc": true, "sortBy": "endingSoon" }
```

Full market history for analysis (~540 rows):

```json
{ "statuses": ["all"], "sortBy": "newest", "maxItems": 1000 }
```

Solana/Rust hunter:

```json
{ "searchText": "solana", "statuses": ["live", "upcoming"] }
```

### How to schedule this Actor (recommended setup)

Contests launch and close on a weekly rhythm, and the good ones fill up with hunters from day one. A scheduled run is how you hear about a contest on launch day instead of day four.

1. Run the Actor once with your input and check the results.
2. On the Actor page open the **…** menu and choose **Schedule Actor** (or go to [Schedules](https://console.apify.com/schedules) and click **Create new**).
3. Set the cron expression:
   - `0 8 * * *` — every morning. The natural cadence for contest boards.
   - `0 8 * * 1,4` — Monday and Thursday. Enough if you only take one contest at a time.
   - `0 */6 * * *` — every 6 hours, when you're racing for a seat in contests that cap participants.
4. Attach your saved input. The default board is small (tens of rows), so **every scheduled run costs about a cent**.
5. Add an integration so the board comes to you: **Integrations → Slack / Discord webhook / Google Sheets / Zapier / Make**, triggered on *Run succeeded*.

**Catching launches:** schedule `{ "statuses": ["upcoming"], "sortBy": "startingSoon" }` daily. Anything new at the top is a contest that was just announced — before the crowd commits their calendar.

### Coverage, honestly

- **Sherlock** — full history via their public API (~300 contests).
- **Cantina** — full history via their public API (~145 competitions, including anonymized private ones).
- **CodeHawks** — all competitive audits (~45; First Flights are tagged `first-flight`).
- **Code4rena** — the ~50 most recent audits: the complete active board plus recent history. Their archive beyond that is not server-rendered, and we would rather tell you that than pretend.

### Why this Actor

- **Four platforms, one schema, one run** — no other Actor on the Store covers the competitive-audit boards at all (checked Aug 2026).
- **HTTP-only** — seconds per run, no proxy costs baked into the price.
- **Defensive parsing** — each platform is fetched independently; one platform having a bad day degrades the run instead of killing it, and the run summary tells you exactly which source failed.
- **Pay per event** — a tiny start fee plus a per-contest fee. The default actionable board costs about **a cent per run**; the full 540-row history about $0.66.
- **No free-plan cap** — free-plan users get the same board as everyone else.

Hunting **bug bounties** rather than contests? The same treatment for the Immunefi board — max bounty, KYC/PoC/fee friction, opportunity score across 240+ programs — is here: [Immunefi Bug Bounty & Audit Competition Scraper](https://apify.com/tactful_anvil/immunefi-bug-bounty-audit-competition-scraper).

### FAQ

**Is this legal?** The Actor reads only public contest directories — the same pages and public APIs anyone sees without logging in. No login, no private data, no bypassing access controls. Review each platform's terms for your use case.

**Why is `prizePoolUsd` null on some contests?** The pool is denominated in a volatile token (ETH, OP…) and the platform published no USD rate. The original amount is always in `prizeRaw` / `prizeAmount` / `prizeCurrency`. We don't invent exchange rates.

**Why does `status` sometimes disagree with the platform's badge?** `status` is computed from start/end timestamps against the current clock, so it means the same thing across all four platforms. The platform's own label is preserved in `statusRaw`.

**A contest has `title: null`?** Cantina anonymizes private contests in its public API. The row is real (pot, dates, findings count are published); the name genuinely is not public.

**Found a bug, or want another platform (Hats, Codarena forks, …)?** Open a ticket on the **Issues** tab.

### Changelog

- **0.1** — Initial release: Code4rena + Sherlock + CodeHawks + Cantina, normalized schema, USD conversion for stablecoin pools, clock-derived status, opportunity score, pay-per-event.

### Was this Actor useful?

If it replaced your weekly four-tab contest crawl, a short review on the Store page helps other researchers decide whether to try it. Reviews are the only signal buyers have before they spend anything.

If something is wrong instead, please open a ticket on the **Issues** tab rather than leaving it broken — parser drift and field requests get fixed.

# Actor input Schema

## `sources` (type: `array`):

Which contest platforms to pull. Default: all four.

## `statuses` (type: `array`):

Which contest lifecycle states to return. `live` = submissions open now, `upcoming` = announced but not started, `judging` = ended, results pending, `ended` = finished, `all` = everything. Default is the actionable board: live + upcoming.

## `minPrizeUsd` (type: `integer`):

Only contests whose prize pool is a known USD value of at least this amount. Contests with a non-stablecoin pool and no reliable rate have prizePoolUsd = null and are excluded by this filter.

## `publicOnly` (type: `boolean`):

Drop private and invite-only contests you cannot actually join.

## `excludeKyc` (type: `boolean`):

Drop contests that require identity verification (flag published by CodeHawks and Cantina; other platforms report null and are kept).

## `searchText` (type: `string`):

Case-insensitive match against title, organizer, platform and tags (e.g. "solana", "lending", "rust").

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

Result order.

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

Hard cap on returned (and billed) results.

## Actor input object example

```json
{
  "sources": [
    "code4rena",
    "sherlock",
    "codehawks",
    "cantina"
  ],
  "statuses": [
    "live",
    "upcoming"
  ],
  "publicOnly": false,
  "excludeKyc": false,
  "sortBy": "opportunity",
  "maxItems": 500
}
```

# Actor output Schema

## `contests` (type: `string`):

Every contest returned by the run, one row each. Sorted by the sortBy input (default: opportunity score).

# 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 = {
    "sources": [
        "code4rena",
        "sherlock",
        "codehawks",
        "cantina"
    ],
    "statuses": [
        "live",
        "upcoming"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tactful_anvil/web3-audit-contest-aggregator").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 = {
    "sources": [
        "code4rena",
        "sherlock",
        "codehawks",
        "cantina",
    ],
    "statuses": [
        "live",
        "upcoming",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("tactful_anvil/web3-audit-contest-aggregator").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 '{
  "sources": [
    "code4rena",
    "sherlock",
    "codehawks",
    "cantina"
  ],
  "statuses": [
    "live",
    "upcoming"
  ]
}' |
apify call tactful_anvil/web3-audit-contest-aggregator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tactful_anvil/web3-audit-contest-aggregator"
        }
    }
}

```

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/e05WWwrdoDEa9Bj25/builds/bF2tXYze2adL7BLI4/openapi.json
