# Fish Stocking Reports Scraper (`automation-lab/utah-fish-stocking-reports`) Actor

Export Utah DWR fish stocking events by waterbody, species, county, quantity, length, and date.

- **URL**: https://apify.com/automation-lab/utah-fish-stocking-reports.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Sports
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.24 / 1,000 item extracteds

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/actors/running/actors-in-store.md#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

## Fish Stocking Reports Scraper

Export official Utah Division of Wildlife Resources (Utah DWR) fish stocking reports as clean, analysis-ready records. Each dataset item includes the waterbody, county, species, quantity, average fish length, stocking date, report year, agency, and source URL.

Use the Actor for fishing trip planning, stocking-season research, watershed analysis, or a scheduled data pipeline. It reads the public DWR Apps Utah report without a login and saves normalized JSON, CSV, Excel, XML, RSS, or HTML through Apify's dataset exports.

### What does this Actor do?

The Actor collects stocking-event rows from the official Utah DWR report for one or more years. It can narrow the result to a date range, waterbody name, counties, or exact species labels.

Results are sorted newest first. `maxItems` limits the number saved after every filter is applied.

This Actor is intentionally Utah-specific. It does not combine reports from other states, geocode waterbodies, predict fishing conditions, or infer unreported stocking events.

### Who is it for?

- **Anglers and trip planners** checking where and when Utah waters were stocked.
- **Fishing guides and outdoor publishers** preparing current stocking summaries.
- **Fisheries analysts and researchers** comparing quantities, species, and average lengths across report years.
- **Data teams** loading repeatable Utah DWR snapshots into spreadsheets, databases, or dashboards.
- **Automation builders** scheduling report exports and comparing snapshots in a downstream workflow.

### Why use it?

The public report is designed for browser reading. This Actor converts its rows into stable typed fields and handles multi-year collection, filtering, date normalization, newest-first ordering, and dataset export in one run.

No Utah account, browser automation, or proxy configuration is required. The source remains Utah DWR; every row includes an official report link for traceability.

### What fish stocking data is extracted?

| Field | Meaning |
| --- | --- |
| `stockingEventId` | Stable source-derived identifier, including duplicate occurrence order |
| `waterbody` | Water name shown by Utah DWR |
| `county` | Utah county reported for the water |
| `species` | DWR species label, such as `RAINBOW` or `TIGER TROUT` |
| `quantity` | Number of fish in the reported stocking event |
| `averageLengthInches` | Reported average fish length in inches |
| `stockingDate` | Stocking date normalized to `YYYY-MM-DD` |
| `year` | Requested Utah DWR report year |
| `agency` | `Utah Division of Wildlife Resources` |
| `sourceUrl` | Official report URL for the year |
| `scrapedAt` | UTC collection timestamp |

### How to run the Utah fish stocking report scraper

1. Open the Actor in Apify Console.
2. Choose one or more **Report years**. The default uses the current report year.
3. Optionally set a date range, a partial waterbody name, exact counties, or exact species labels.
4. Set **Maximum events** for the largest dataset you need.
5. Click **Start**.
6. Open the default dataset and export the events in your preferred format.

A useful first run is:

```json
{
  "years": [2026],
  "maxItems": 100
}
```

### Input parameters

| Input | Type | Default | Description |
| --- | --- | --- | --- |
| `years` | integer array | current year | One to 20 report years from 1990 through the current year |
| `fromDate` | string | — | Inclusive lower date bound in `YYYY-MM-DD` format |
| `toDate` | string | — | Inclusive upper date bound in `YYYY-MM-DD` format |
| `waterbody` | string | — | Case-insensitive partial waterbody match |
| `counties` | string array | — | Case-insensitive exact county names |
| `species` | string array | — | Case-insensitive exact DWR species labels |
| `maxItems` | integer | `1000` | Maximum matching events to save, from 1 to 100,000 |

If `years` is omitted and a date range is present, the Actor derives the needed years from that range. If both are supplied, rows must satisfy both scopes.

### Filtering examples

Find Strawberry Reservoir records:

```json
{
  "years": [2026],
  "waterbody": "STRAWBERRY",
  "maxItems": 50
}
```

Collect recent rainbow trout events across two reports:

```json
{
  "years": [2025, 2026],
  "fromDate": "2025-06-01",
  "species": ["RAINBOW"],
  "maxItems": 100
}
```

County and species filters require the labels used by Utah DWR. Waterbody matching is partial, so `STRAWBERRY` can match abbreviated report names.

### Output example

A real current report row has this shape:

```json
{
  "stockingEventId": "fa7c3517ccaab9bf200a72de",
  "waterbody": "BUTTERFLY L Z-1",
  "county": "DUCHESNE",
  "species": "RAINBOW",
  "quantity": 201,
  "averageLengthInches": 11.24,
  "stockingDate": "2026-08-24",
  "year": 2026,
  "agency": "Utah Division of Wildlife Resources",
  "sourceUrl": "https://dwrapps.utah.gov/fishstocking/Fish?y=2026",
  "scrapedAt": "2026-08-25T14:53:39.661Z"
}
```

The identifier and collection timestamp will reflect the actual run. Primary records are always written to the default dataset.

### How much does it cost to export Utah fish stocking events?

Pricing uses one `start` event per run plus one `item` event for each saved stocking event. The BRONZE rate is **$0.03 per run + $0.0004 per event**; higher-volume tiers automatically reduce the per-event rate.

At the BRONZE rate:

| Saved events | BRONZE calculation |
| ---: | ---: |
| 25 | $0.03 + (25 × $0.0004) |
| 100 | $0.03 + (100 × $0.0004) |
| 1,000 | $0.03 + (1,000 × $0.0004) |

Only rows that pass the filters and are saved are charged as `item` events. A no-result run has only the one-time start charge. Apify platform tier assignment and rounding may affect the final amount shown in Console.

### Schedule recurring stocking checks

Use an Apify Schedule to run the same input daily or weekly during stocking season. Each run creates a new dataset snapshot. Send the dataset to your own database, Make, Zapier, Google Sheets, or another integration, then compare `stockingEventId` values to identify records not present in an earlier snapshot.

The Actor does not maintain a hidden cross-run history and does not send alerts by itself. That keeps each result reproducible and lets your workflow decide how long to retain snapshots.

### Export to spreadsheets and data pipelines

From the run's dataset page, choose CSV or Excel for spreadsheet work, or JSON for code and data warehouses. You can also retrieve the dataset programmatically after the run finishes.

Useful workflows include:

- a weekly Utah stocking worksheet grouped by county;
- a waterbody-specific trip-planning feed;
- year-over-year quantity and species analysis;
- a dashboard refreshed from scheduled run datasets;
- a database upsert keyed by `stockingEventId`.

### Run through the Apify API

Set `APIFY_TOKEN` in your environment. Replace `YOUR_TOKEN` only in local experiments; do not commit it.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~utah-fish-stocking-reports/runs?token=$APIFY_TOKEN&waitForFinish=300" \
  -H "Content-Type: application/json" \
  -d '{"years":[2026],"waterbody":"STRAWBERRY","maxItems":50}'
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/utah-fish-stocking-reports').call({
  years: [2026],
  species: ['RAINBOW'],
  maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/utah-fish-stocking-reports').call(run_input={
    'years': [2025, 2026],
    'fromDate': '2025-06-01',
    'species': ['RAINBOW'],
    'maxItems': 100,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with Apify MCP

#### Claude Code

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/utah-fish-stocking-reports"
```

#### Claude Desktop

Add this server to the desktop MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/utah-fish-stocking-reports"
    }
  }
}
```

#### Cursor

Add the same `apify` HTTP server URL under **Settings → MCP**.

#### VS Code

Add the same `apify` HTTP server URL to your workspace or user MCP server configuration.

Example prompts:

- “Export the latest 50 Utah DWR stocking events.”
- “Find 2026 Strawberry Reservoir stocking records and summarize species and quantities.”
- “Collect Utah rainbow trout events since 2025-06-01 for my spreadsheet workflow.”

### Data quality and source limitations

The Actor reports what Utah DWR publishes. Names may be abbreviated, capitalization follows the source, and some waterbody labels may differ from names used on maps. `averageLengthInches` is the source's reported average, not a measurement of every fish.

Historical availability is controlled by the official report. A valid year with no published rows returns an empty dataset. The source can revise or remove records; scheduled snapshots are the right way to preserve change history for your own analysis.

### Reliability and responsible load

The implementation uses the lightweight public report endpoint rather than a browser. It retries transient network or server failures a bounded number of times and fails the run when the report cannot be validated. It does not silently replace a failed year with incomplete data.

Request only the years needed for your workflow. A maximum of 20 years per run limits unnecessary source load.

### Legality and responsible use

This Actor accesses public government report data. Use the output responsibly, follow applicable Utah website terms and laws, and retain source attribution where appropriate. Do not interpret stocking reports as safety guidance, access permission, fishing regulations, or a guarantee that fish remain at a location.

Check current Utah fishing regulations and local access conditions before a trip.

### Troubleshooting

#### Why did my run return no events?

Confirm that the chosen year has published Utah DWR rows and that exact `counties` or `species` labels match the report. Remove optional filters, run a small current-year export, then add filters back one at a time.

#### Why was my input rejected?

Dates must be real calendar dates in `YYYY-MM-DD` form. `fromDate` cannot be later than `toDate`. Years must be unique integers in the supported range, and `maxItems` must be from 1 to 100,000.

#### Why did the run fail with an upstream error?

The Utah DWR report may be temporarily unavailable. Check the run log and retry later. The Actor deliberately fails instead of charging for or returning a partial invalid report.

### FAQ

#### Does this scrape all US state fish stocking reports?

No. It extracts official Utah DWR events only. The narrow scope provides predictable fields and filters for Utah workflows.

#### Does it require a proxy or Utah DWR login?

No. The supported public report route works with direct HTTP and no account.

#### Can it find events by a partial species name?

No. Species values use case-insensitive exact matching to avoid confusing similar labels. Run a broad sample first to inspect current DWR species names.

#### Can it monitor changes automatically?

You can schedule repeated runs and compare their datasets downstream. The Actor itself does not retain prior snapshots or send alerts.

#### Are zero-result runs errors?

No. A valid report and valid filters can naturally produce no matching events. The run succeeds with an empty default dataset.

### Related scrapers

This Actor is currently a standalone Utah DWR data product. Pair its dataset with Apify's built-in schedules, webhooks, dataset exports, and integrations rather than an unrelated scraper. Related Automation Lab Actors will be linked here only when they serve the same verified fisheries workflow.

# Actor input Schema

## `years` (type: `array`):

Utah DWR report years to collect. Up to 20 unique years from 1990 through the current year.

## `fromDate` (type: `string`):

Optional inclusive start date in YYYY-MM-DD format. If years are omitted, the Actor derives them from the date range.

## `toDate` (type: `string`):

Optional inclusive end date in YYYY-MM-DD format.

## `waterbody` (type: `string`):

Optional case-insensitive partial match, for example STRAWBERRY or DEER CREEK.

## `counties` (type: `array`):

Optional exact county names. Matching is case-insensitive, for example Wasatch or Utah.

## `species` (type: `array`):

Optional exact Utah DWR species labels. Matching is case-insensitive, for example RAINBOW or TIGER TROUT.

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

Maximum number of matching stocking events to save, newest first.

## Actor input object example

```json
{
  "years": [
    2026
  ],
  "maxItems": 20
}
```

# Actor output Schema

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

Open the default dataset overview containing one record per matching Utah DWR stocking event.

# 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 = {
    "years": [
        2026
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/utah-fish-stocking-reports").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 = {
    "years": [2026],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/utah-fish-stocking-reports").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 '{
  "years": [
    2026
  ],
  "maxItems": 20
}' |
apify call automation-lab/utah-fish-stocking-reports --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/utah-fish-stocking-reports"
        }
    }
}

```

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/2fXhzbUeQScAsr0NY/builds/YxXyQr4DTDFOgNVLq/openapi.json
