# Give.org BBB Charity Report Scraper (`adam-frank/give-org-charity-reports`) Actor

Extracts BBB Wise Giving Alliance charity accountability reports from Give.org: accreditation status, per-standard results, and org details, priced pay-per-result.

- **URL**: https://apify.com/adam-frank/give-org-charity-reports.md
- **Developed by:** [Adam Schepis](https://apify.com/adam-frank) (community)
- **Categories:** Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 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/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

## Give.org BBB Charity Report Scraper

Extracts BBB Wise Giving Alliance charity accountability reports from Give.org, priced pay-per-result.

### What you get

- Per charity: name, report URL, EIN (if shown), location, cause/category, accreditation status, pass/fail on all 20 BBB Standards for Charity Accountability, report issue/expiry dates, and website.
- Structured, ready-to-use data — no scraper to build or maintain yourself.
- Pay only for results: $0.004 per charity report, nothing for failed or empty runs.
- Runs on Apify's infrastructure with automatic proxy rotation and retries.

### Input

| Field | Type | Required | Description |
|---|---|---|---|
| `startUrls` | array of URLs | one of `startUrls`/`searchQuery` | Give.org charity report pages (`https://give.org/charity-reviews/<category>/<name>`) and/or listing pages (`https://give.org/search?searchTerm=...` or `https://give.org/national-charity-reviews`). Listing pages are crawled for report links; report pages are scraped directly. |
| `searchQuery` | string | one of `startUrls`/`searchQuery` | Builds `https://give.org/search?searchTerm=<query>`. See the caveat under "Why this actor" below. |
| `maxResults` | integer | no (default 20) | Stops the run (and pay-per-event charging) once this many charity reports have been produced. |

Example input:

```json
{
    "startUrls": [
        { "url": "https://give.org/charity-reviews/human-services/american-red-cross-in-washington-dc-9999-679" },
        { "url": "https://give.org/national-charity-reviews" }
    ],
    "maxResults": 20
}
```

### Output example

This is a real, verified sample from a local run:

```json
{
    "charityName": "American Red Cross",
    "url": "https://give.org/charity-reviews/human-services/american-red-cross-in-washington-dc-9999-679",
    "ein": null,
    "location": "431 18th Street NW, Washington, DC, 20006",
    "phone": "(800) 733-2767",
    "category": "Human Services",
    "website": "https://www.redcross.org",
    "accreditationStatus": "meets_all_standards",
    "accreditationStatusLabel": "Accredited Charity",
    "standard_1": "Meets Standards",
    "standard_2": "Meets Standards",
    "standard_3": "Meets Standards",
    "standard_20": "Meets Standards",
    "reportDate": "September 2026",
    "reportExpires": "September 2028",
    "scrapedAt": "2026-09-08T23:29:32.171Z"
}
```

(`standard_4` through `standard_19` omitted above for brevity — every record has all 20.) A report the charity declined to have evaluated (`accreditationStatus: "did_not_disclose"`) has `standard_1`...`standard_20` all `null`, since no matrix is published for those; every other field is still populated.

`standard_1`...`standard_20` are the 20 BBB Standards for Charity Accountability, in this fixed order:

| # | Standard | # | Standard |
|---|---|---|---|
| 1 | Board Oversight | 11 | Audit Report |
| 2 | Board Size | 12 | Detailed Expense Breakdown |
| 3 | Board Meetings | 13 | Accurate Expense Reporting |
| 4 | Board Compensation | 14 | Budget Plan |
| 5 | Conflict of Interest | 15 | Truthful Materials |
| 6 | Effectiveness Policy | 16 | Annual Report |
| 7 | Effectiveness Report | 17 | Website Disclosures |
| 8 | Program Expenses | 18 | Donor Privacy |
| 9 | Fundraising Expenses | 19 | Cause Marketing Disclosures |
| 10 | Accumulating Funds | 20 | Complaints |

Each standard's value is one of: `"Meets Standards"`, `"Standards Not Met"`, `"Did Not Disclose"`, `"Unable To Verify"`, `"Review In Progress"`, or `null` (no matrix published for this charity's report).

`accreditationStatus` is one of: `meets_all_standards`, `does_not_meet_standards`, `did_not_disclose`, `review_in_progress`, `unable_to_verify`. `accreditationStatusLabel` carries Give.org's own display text for the same value.

Every dataset item has the same shape. Download results as JSON, CSV, Excel, or via the Apify API.

### Pricing

This Actor uses [pay-per-event pricing](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event). You are charged only for the `result` event, once per charity report produced; the exact per-event price is set in Apify Console at publish time and shown on the Actor's Store page before you run it.

| Event | When it's charged |
|---|---|
| `result` | Once per charity report, up to `maxResults` |

### Why this actor

Give.org (the BBB Wise Giving Alliance) publishes free charity accountability reports one at a time, with no bulk export and no public API. This actor turns any charity report page, or a listing/search page full of them, into structured JSON in one call — useful for donor-research tools, nonprofit-sector datasets, and due-diligence workflows that need accreditation status and standards-level detail at scale.

Caveat on `searchQuery`: Give.org's search form accepts a `searchTerm` parameter, but as tested it does not filter results server-side — every query returns the same default listing (paginated, ~6,400 charities total). The parameter is still wired up so the actor keeps working (and starts actually filtering) if that changes; for now, prefer `startUrls` with direct report URLs or the `/national-charity-reviews` listing (a single page indexing ~1,700 report links) if you need deterministic, specific charities.

### How it works

- Report pages render their content client-side via a WordPress AJAX call (`admin-ajax.php?action=give_load_charity_report`) using a nonce embedded in the page. This actor fetches the report page first (the same request an anonymous visitor's browser makes), reads the bureau code / source ID / nonce out of it, then makes that same AJAX call itself to get the report HTML — no login, no data beyond what's shown to any visitor.
- Listing pages (search results and the national A-Z index) are ordinary server-rendered HTML; report links (and, on search-result cards, a category label) are read directly from the page.
- `maxConcurrency` capped at 3.

### Robots.txt

`https://give.org/robots.txt` returned 404 (no robots.txt) when checked while building this actor (2026-09-08). There were no Disallow paths to honor. This should be re-checked periodically in case the site adds one.

### Notes for buyers

- EIN was not shown on any charity report sampled while building this actor (not this environment's report template, at least) — the field is extracted defensively in case a report does show one, but expect `null` in most/all records today.
- `location` joins the report's address lines with `, ` (street, then city/state/ZIP).
- `category` uses the human-readable label shown on a listing page's result card when the report was reached that way; for report URLs given directly (or reached via the national listing, which doesn't show a category label on its cards), it's derived from the report URL's category segment against Give.org's fixed cause taxonomy.
- Seed 3 (`smoke/seed-3.json`) crawls `/national-charity-reviews`, a single page indexing roughly 1,700 report links, and stops at `maxResults` — a good way to see the budget cutoff in action on a page with far more links than you asked for.

### Reference docs used to build this actor

- Apify SDK for JS: https://docs.apify.com/sdk/js/
- Pay-per-event monetization overview: https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event
- Pay-per-event SDK guide (`Actor.charge`, `ChargingManager`, local test mode): https://docs.apify.com/sdk/js/docs/concepts/pay-per-event
- `Actor.charge` API reference: https://docs.apify.com/sdk/js/reference/class/Actor
- `.actor/actor.json` reference: https://docs.apify.com/platform/actors/development/actor-definition/actor-json
- Built with [Crawlee](https://crawlee.dev) and the [Apify SDK for JavaScript](https://docs.apify.com/sdk/js/).

# Actor input Schema

## `startUrls` (type: `array`):

Give.org charity report pages (https://give.org/charity-reviews/<category>/<name>) and/or listing pages (https://give.org/search?searchTerm=... or https://give.org/national-charity-reviews). Listing pages are crawled for report links; report pages are scraped directly.

## `searchQuery` (type: `string`):

Used only when "Start URLs" is empty. Builds https://give.org/search?searchTerm=<query>. Note: on the live site this parameter does not currently filter results server-side (it always returns the same default listing) — kept here for forward compatibility and so the Actor still works if Give.org's search starts honoring the term.

## `maxResults` (type: `integer`):

Stops the run (and pay-per-event charging) once this many charity reports have been produced.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://give.org/national-charity-reviews"
    }
  ],
  "searchQuery": "red cross",
  "maxResults": 20
}
```

# Actor output Schema

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

Dataset containing all scraped records

# 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 = {
    "startUrls": [
        {
            "url": "https://give.org/national-charity-reviews"
        }
    ],
    "searchQuery": "red cross"
};

// Run the Actor and wait for it to finish
const run = await client.actor("adam-frank/give-org-charity-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 = {
    "startUrls": [{ "url": "https://give.org/national-charity-reviews" }],
    "searchQuery": "red cross",
}

# Run the Actor and wait for it to finish
run = client.actor("adam-frank/give-org-charity-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 '{
  "startUrls": [
    {
      "url": "https://give.org/national-charity-reviews"
    }
  ],
  "searchQuery": "red cross"
}' |
apify call adam-frank/give-org-charity-reports --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,adam-frank/give-org-charity-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/YYjCScnC9gwHJaIUX/builds/jTuLgKidvVSJRm0cx/openapi.json
