# NOAA Essential Fish Habitat Consultation Screener (`automation-lab/noaa-essential-fish-habitat-consultation-screener`) Actor

Screen U.S. project points, bounding boxes, and GeoJSON areas against NOAA EFH and HAPC layers; export species, life stages, councils, caveats, and official references for permitting triage.

- **URL**: https://apify.com/automation-lab/noaa-essential-fish-habitat-consultation-screener.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.84 / 1,000 project area screeneds

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

## NOAA Essential Fish Habitat Consultation Screener

Screen U.S. coastal and offshore project points or areas against official **NOAA essential fish habitat** (EFH) and Habitat Areas of Particular Concern (HAPC) GIS layers.

The Actor returns one structured screening record per project area, including intersecting managed species or management units, life stages, fishery management councils, NOAA regions, habitat metadata, source caveats, and official references.

Use it for early environmental-permitting triage. It is a planning tool, not a legal determination and not a replacement for project-specific review by NOAA Fisheries.

### What does this Actor do?

The Actor accepts any mix of:

- WGS84 longitude/latitude points;
- WGS84 bounding boxes;
- GeoJSON Polygon geometries;
- GeoJSON MultiPolygon geometries.

For each project area it queries NOAA's public nationwide EFH layer and, by default, NOAA's HAPC layer.

It aggregates all intersections into a single project-level record, so a batch of 20 project areas produces 20 billable screening rows rather than hundreds of separately billed source features.

### Who is it for?

This Actor is designed for:

- environmental consultants performing desktop constraints reviews;
- infrastructure and coastal-development teams screening candidate sites;
- permitting specialists preparing early agency-coordination notes;
- fisheries and marine-resource analysts checking EFH designations;
- GIS teams enriching project portfolios with official habitat context;
- due-diligence platforms that need a repeatable JSON screening step.

A typical workflow is to screen locations early, retain the source references and caveats, and send flagged projects for professional review.

### Why use this NOAA EFH screener?

- **Official source layers:** spatial results come from NOAA-linked public ArcGIS services used for nationwide EFH and HAPC data.
- **Three geometry modes:** use a precise point, a fast bounding box, or a project-area Polygon/MultiPolygon.
- **Project-level output:** receive one integration-friendly record per submitted project.
- **Consultation triage:** quickly identify locations where project-specific EFH review may be warranted.
- **Source transparency:** retain source object IDs, plan/document references, URLs, and NOAA caveats.
- **Bounded execution:** explicit input and result limits prevent accidentally unbounded GIS requests.
- **No browser or proxy required:** the Actor uses anonymous structured GIS endpoints directly.

### What NOAA Essential Fish Habitat data is returned?

| Field | Meaning |
| --- | --- |
| `projectId` | Your project ID, or a generated positional ID |
| `inputType` | `point`, `bbox`, or `geoJson` |
| `intersectsEssentialFishHabitat` | Whether one or more EFH features intersect |
| `consultationReviewRecommended` | Planning flag for follow-up review, not a legal conclusion |
| `habitatAreaOfParticularConcernPresent` | Whether one or more HAPC features intersect |
| `efhMatchCount` / `hapcMatchCount` | Number of source features found |
| `managedSpecies` | Unique species or management-unit names |
| `lifeStages` | Unique life stages represented in EFH matches |
| `fisheryManagementCouncils` | Council codes or names in matching source records |
| `noaaRegions` | NOAA region values reported by the source |
| `efhMatches` | Detailed normalized EFH source records |
| `hapcMatches` | Detailed normalized HAPC source records |
| `dataCaveats` | Unique caveats copied from matching NOAA records |
| `sourceReferences` | Official mapper and layer links |
| `resultsTruncated` | Whether your per-layer safety limit was reached |
| `screenedAt` | UTC timestamp for the screening |

Fields unavailable in a source feature are returned as `null`. Empty result groups are returned as empty arrays.

### How to screen a project area

1. Open the Actor input page.
2. Add one or more objects to `projectAreas`.
3. Give each project a stable `id` for downstream joins.
4. Add exactly one geometry to each item: `point`, `bbox`, or `geoJson`.
5. Keep `includeHapc` enabled unless you only need EFH designations.
6. Run the Actor.
7. Review the default dataset and export it as JSON, CSV, Excel, or another supported format.
8. Treat flagged results and source caveats as inputs to professional project review.

The prefilled Boston Harbor point returns real EFH intersections and is a quick first-run test.

### Input parameters

#### `projectAreas`

Required array with 1–100 project-area objects.

Each item supports:

- `id` — optional stable project identifier;
- `name` — optional display name;
- `point` — `{ "longitude": number, "latitude": number }`;
- `bbox` — `[west, south, east, north]`;
- `geoJson` — a Polygon or MultiPolygon geometry object.

Supply exactly one geometry mode per item. All coordinates must use WGS84 longitude/latitude (`EPSG:4326`).

A GeoJSON Feature wrapper or FeatureCollection is not accepted; pass its `geometry` value.

#### `includeHapc`

Optional boolean, default `true`.

When enabled, the Actor also queries NOAA's Habitat Areas of Particular Concern layer and includes normalized HAPC details.

#### `maxMatchesPerLayer`

Optional integer from 1 to 10,000, default 2,000.

This is a per-project, per-layer safety limit. If matching source features exceed it, `resultsTruncated` is `true`.

### Point input example

```json
{
  "projectAreas": [
    {
      "id": "boston-harbor",
      "name": "Boston Harbor project point",
      "point": {
        "longitude": -71.05,
        "latitude": 42.35
      }
    }
  ],
  "includeHapc": true
}
```

### Bounding-box input example

Bounding boxes use `[west, south, east, north]` order.

```json
{
  "projectAreas": [
    {
      "id": "sf-bay-shoreline",
      "name": "San Francisco Bay shoreline",
      "bbox": [-122.52, 37.70, -122.34, 37.83]
    }
  ]
}
```

A box finds any habitat polygon intersecting any part of the box. It does not mean the full box is habitat.

### GeoJSON area input example

```json
{
  "projectAreas": [
    {
      "id": "tampa-bay-area",
      "name": "Tampa Bay project area",
      "geoJson": {
        "type": "Polygon",
        "coordinates": [
          [
            [-82.58, 27.88],
            [-82.50, 27.88],
            [-82.50, 27.94],
            [-82.58, 27.94],
            [-82.58, 27.88]
          ]
        ]
      }
    }
  ]
}
```

Polygon rings must be closed: the first and last coordinate positions must match.

### Output example

This shortened example reflects the Actor's current project-level output shape:

```json
{
  "projectId": "boston-harbor",
  "projectName": "Boston Harbor project point",
  "inputType": "point",
  "queryGeometry": {
    "longitude": -71.05,
    "latitude": 42.35
  },
  "intersectsEssentialFishHabitat": true,
  "consultationReviewRecommended": true,
  "habitatAreaOfParticularConcernPresent": true,
  "efhMatchCount": 61,
  "hapcMatchCount": 1,
  "resultsTruncated": false,
  "managedSpecies": [
    "Atlantic Cod",
    "Atlantic Wolffish",
    "Winter Flounder"
  ],
  "lifeStages": ["ALL", "Adult", "Eggs", "Juvenile"],
  "fisheryManagementCouncils": ["MAFMC", "NEFMC"],
  "efhMatches": [
    {
      "sourceObjectId": 612,
      "speciesOrManagementUnit": "Atlantic Wolffish",
      "lifeStage": "ALL",
      "designationType": "EFH",
      "fisheryManagementCouncil": "NEFMC",
      "sourceDocumentUrl": "https://www.habitat.noaa.gov/application/efhmapper/oa2_efh_hapc.pdf#page=16",
      "dataCaveat": "Source-specific caveat copied from NOAA"
    }
  ],
  "screeningNotice": "Planning-level screening only. Confirm current information and next steps with NOAA Fisheries.",
  "sourceReferences": [
    {
      "title": "NOAA Essential Fish Habitat Mapper",
      "url": "https://www.habitat.noaa.gov/apps/efhmapper/"
    }
  ],
  "screenedAt": "2026-09-07T12:00:00.000Z"
}
```

The complete output preserves every matching EFH and HAPC record up to the selected safety limit.

### Understanding the consultation indicator

`consultationReviewRecommended: true` means the supplied geometry intersects at least one EFH or HAPC source feature.

It does **not** determine:

- whether a federal action or permit nexus exists;
- whether consultation is legally required;
- whether the project will adversely affect EFH;
- what conservation recommendations may apply;
- whether local or newer project-specific mapping changes the result.

Use the indicator to prioritize review, not to replace legal, permitting, biological, or agency advice.

### How much does it cost to screen NOAA Essential Fish Habitat?

Pricing uses one `start` event per run plus one `screening` event for each project-area result.

The current source configuration uses a **$0.005 start fee**. Project-screening prices vary by Apify plan:

| Plan | Price per project-area screening |
| --- | ---: |
| Free | $0.00736 |
| Bronze | $0.00640 |
| Silver | $0.004992 |
| Gold | $0.00384 |
| Platinum | $0.00384 |
| Diamond | $0.00384 |

Bronze examples, including the start event:

- 1 project area: about **$0.0114**;
- 10 project areas: about **$0.0690**;
- 100 project areas: about **$0.6450**.

A project with no intersections still produces and charges one useful screening record. EFH features and HAPC features nested inside that result are not separately charged.

Apify platform-compute charges, subscription rules, taxes, or account-specific terms may also apply. Check the live Actor pricing panel before a large run.

### Batch and scheduled workflows

Use stable `id` values to join outputs back to your project inventory.

Common repeatable workflows include:

- screening a portfolio of candidate coastal sites before detailed diligence;
- running the same project boundaries on a schedule and comparing saved datasets;
- routing only `consultationReviewRecommended: true` rows to a permitting queue;
- expanding `efhMatches` into a species-by-project table in your data warehouse;
- retaining `screenedAt`, source object IDs, references, and caveats for an audit trail.

The Actor does not itself send alerts or compare historical datasets. Use Apify schedules, webhooks, or your own pipeline for those steps.

### API usage with cURL

Start a run through the Apify API:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~noaa-essential-fish-habitat-consultation-screener/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "projectAreas": [
      {
        "id": "boston-harbor",
        "point": {"longitude": -71.05, "latitude": 42.35}
      }
    ],
    "includeHapc": true
  }'
```

For production integrations, prefer sending the token in an authorization header rather than storing it in source code or logs.

### API usage with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor(
  'automation-lab/noaa-essential-fish-habitat-consultation-screener'
).call({
  projectAreas: [
    {
      id: 'sf-bay-shoreline',
      bbox: [-122.52, 37.70, -122.34, 37.83],
    },
  ],
  includeHapc: true,
});

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

### API usage with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor(
    'automation-lab/noaa-essential-fish-habitat-consultation-screener'
).call(run_input={
    'projectAreas': [
        {
            'id': 'tampa-bay-area',
            'geoJson': {
                'type': 'Polygon',
                'coordinates': [[
                    [-82.58, 27.88], [-82.50, 27.88],
                    [-82.50, 27.94], [-82.58, 27.94],
                    [-82.58, 27.88],
                ]],
            },
        },
    ],
})

items = client.dataset(run['defaultDatasetId']).list_items().items
print(items[0]['managedSpecies'])
```

### Use with MCP and AI assistants

Add the Actor to Claude Code through Apify MCP:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/noaa-essential-fish-habitat-consultation-screener"
```

#### Claude Desktop setup

Add this server object to Claude Desktop's MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/noaa-essential-fish-habitat-consultation-screener"
    }
  }
}
```

#### Cursor setup

Open **Cursor Settings → MCP**, add a remote server named `apify`, and use the same URL from the JSON above.

#### VS Code setup

Add the same remote `apify` MCP URL through your VS Code MCP extension or workspace MCP configuration.

Example prompts:

- "Screen longitude -71.05, latitude 42.35 for NOAA EFH and summarize managed species and caveats."
- "Check this GeoJSON Polygon for EFH and HAPC intersections and list the responsible councils."
- "Run the NOAA EFH screener for these 25 project points and return only rows needing consultation review."

AI-generated summaries should preserve the Actor's planning-only notice and source caveats.

### Export and integration patterns

The default dataset can be exported as JSON, CSV, Excel, XML, RSS, or JSONL through Apify.

Recommended patterns:

- keep the nested JSON output when preserving all source metadata;
- use `projectId` as the durable join key;
- flatten `efhMatches` in a warehouse when each species/life-stage record needs its own row;
- filter on `resultsTruncated` and rerun with a larger safe limit before relying on an incomplete set;
- store the source references with project decisions;
- trigger downstream review through an Apify webhook after successful runs.

CSV exports may serialize nested arrays and objects as JSON strings. JSON or JSONL is usually best for full-fidelity output.

### Limits and reliability

- Each run accepts up to 100 project areas.
- Each area accepts exactly one geometry mode.
- GeoJSON is limited to Polygon and MultiPolygon geometry objects.
- Coordinates must be WGS84 longitude/latitude.
- Source matches are capped independently for EFH and HAPC by `maxMatchesPerLayer`.
- Requests time out after 30 seconds.
- Transient timeouts, HTTP 429, and HTTP 5xx responses receive up to three bounded attempts.
- Invalid inputs and deterministic source errors are not retried.
- The Actor returns one row even when a valid project has no intersections.

Large, highly detailed polygons increase request size and source processing time. Simplify boundaries to the precision needed for screening.

### Data sources and freshness

The Actor queries public ArcGIS layers referenced by the NOAA EFH workflow at run time.

Primary references:

- [NOAA Essential Fish Habitat Mapper](https://www.habitat.noaa.gov/apps/efhmapper/)
- [Nationwide EFH ArcGIS layer](https://services2.arcgis.com/FiaPA4ga0iQKduv3/arcgis/rest/services/nationwide_efh_1/FeatureServer/0)
- [Habitat Areas of Particular Concern ArcGIS layer](https://services2.arcgis.com/FiaPA4ga0iQKduv3/arcgis/rest/services/Habitat_Areas_of_Particular_Concern_1/FeatureServer/0)

`screenedAt` records when the query ran, not when NOAA last revised every underlying designation.

NOAA source fields occasionally contain blanks, legacy labels, typographical errors, or broad mapping caveats. The Actor normalizes blank and `Unknown` text to `null` but does not rewrite substantive source content.

### Responsible use and legal considerations

The Actor accesses public government GIS services without authentication.

Use it responsibly:

- keep request volume bounded;
- do not misrepresent a screening result as agency concurrence;
- preserve source caveats and references;
- confirm decisions against current NOAA guidance and project-specific facts;
- obtain qualified environmental and legal advice where appropriate;
- comply with Apify's terms and your applicable laws and contracts.

No personal data is requested or intentionally collected by this Actor.

### Troubleshooting

#### Why did an inland project return no matches?

A valid no-match result is expected outside mapped coastal and marine EFH. The Actor still returns one row with zero counts and false intersection/review flags.

#### Why is `resultsTruncated` true?

The project intersected more source features than `maxMatchesPerLayer` allowed. Increase the limit within the supported range, or narrow/simplify the project geometry.

#### Why was my GeoJSON rejected?

Confirm that you supplied a Polygon or MultiPolygon geometry rather than a Feature or FeatureCollection, used longitude/latitude order, kept coordinates inside WGS84 bounds, and closed every ring.

#### Why does a bounding box return many species?

Every feature touching any portion of the box counts as an intersection. Use the actual project Polygon when a broad box creates too much screening noise.

#### Does `consultationReviewRecommended` mean consultation is required?

No. It means a source-layer intersection was found and project-specific review may be warranted. Legal applicability depends on facts this GIS screen does not determine.

#### What happens if NOAA's service is temporarily unavailable?

The Actor retries transient timeouts, rate limits, and server errors with bounded backoff. If the service remains unavailable, the run fails rather than returning a misleading empty result.

### FAQ

#### Does the Actor return source geometry?

No. It sends your geometry for an intersection query but does not download the often-large source polygons. This keeps outputs and transfer costs practical.

#### Can I mix points, boxes, and GeoJSON in one run?

Yes. Each project item uses one geometry type, and a batch may mix all three.

#### Are HAPC matches separately charged?

No. EFH and HAPC details are included inside the single charged project-area screening result.

#### Can I turn off HAPC queries?

Yes. Set `includeHapc` to `false` when only nationwide EFH designations are needed.

#### Does the Actor cover projects outside the United States?

It accepts valid WGS84 coordinates, but its product scope and source layers are U.S. NOAA EFH screening. Locations outside source coverage normally return no matches.

#### Can this replace NOAA consultation tools or agency contact?

No. It automates an initial GIS intersection check and preserves references for follow-up.

### Related Actors

- [NOAA Storm Events Database Scraper](https://apify.com/automation-lab/noaa-storm-events-database-scraper) — export historical NOAA storm-event records for hazard and incident analysis. It is a separate weather-history workflow, not an EFH consultation screen.

Combine related outputs only when each source is relevant to your project's documented diligence process.

### Support

For reproducible help, include:

- a sanitized input geometry;
- the run ID;
- the project ID;
- whether HAPC was enabled;
- the full error message or unexpected field;
- what result you expected and why.

Do not include confidential project details when a generalized geometry or minimal reproduction is sufficient.

# Actor input Schema

## `projectAreas` (type: `array`):

One to 100 project locations. Each item must contain exactly one geometry: point, bbox, or geoJson.

## `includeHapc` (type: `boolean`):

Also query NOAA's HAPC layer and include any intersecting priority habitat areas.

## `maxMatchesPerLayer` (type: `integer`):

Safety limit for EFH and HAPC features returned for each project area. Results report when this limit truncates a layer.

## Actor input object example

```json
{
  "projectAreas": [
    {
      "id": "boston-harbor",
      "name": "Boston Harbor project point",
      "point": {
        "longitude": -71.05,
        "latitude": 42.35
      }
    }
  ],
  "includeHapc": true,
  "maxMatchesPerLayer": 2000
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing one complete screening record per project area.

# 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 = {
    "projectAreas": [
        {
            "id": "boston-harbor",
            "name": "Boston Harbor project point",
            "point": {
                "longitude": -71.05,
                "latitude": 42.35
            }
        }
    ],
    "includeHapc": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/noaa-essential-fish-habitat-consultation-screener").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 = {
    "projectAreas": [{
            "id": "boston-harbor",
            "name": "Boston Harbor project point",
            "point": {
                "longitude": -71.05,
                "latitude": 42.35,
            },
        }],
    "includeHapc": True,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/noaa-essential-fish-habitat-consultation-screener").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 '{
  "projectAreas": [
    {
      "id": "boston-harbor",
      "name": "Boston Harbor project point",
      "point": {
        "longitude": -71.05,
        "latitude": 42.35
      }
    }
  ],
  "includeHapc": true
}' |
apify call automation-lab/noaa-essential-fish-habitat-consultation-screener --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/noaa-essential-fish-habitat-consultation-screener"
        }
    }
}
```

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/jqQ3r66EL5Kc11ccs/builds/6jG11p9f9wm4e8QI8/openapi.json
