DEV Community

Cover image for How to look up any charity by name or registration number in 100+ countries?
Matt Timmermans for GiveRadar

Posted on

How to look up any charity by name or registration number in 100+ countries?

If you have ever built something that touches nonprofits, a donation flow, a grant tool, or a CRM import, you have probably hit the same wall: every country keeps its own charity register, and none of them look alike. So, I (Matt Timmermans) decided to solve this problem by building GiveRadar.

This post walks through what the official registers offer, where the friction is, and how I query all of them through one API at GiveRadar. There is code for curl, Python, and AI agents along the way.

Why charity data is harder than it looks

The problem is not that the data is hidden. Most of it is public. The problem is that each register uses a different identifier, a different format, and a different way to access it.

Country Identifier Looks like
United States EIN 9 digits, often written 12-3456789
England and Wales Charity number 6 or 7 digits
Scotland Scottish charity number SC followed by 6 digits
Canada Business Number (BN) 9 digits + RR + 4 digits
Australia ABN 11 digits
Netherlands RSIN 9 digits

So a "charity number" field in your form means something different in every country. And a name search is worse, because names repeat. Many organizations are called some variation of "Community Foundation".

Option 1: go to the registers directly

If you only need one country, the official source is usually the right call:

  • United States: the IRS publishes the Exempt Organizations Business Master File as bulk CSV downloads, and Form 990 filings as bulk files. ProPublica's Nonprofit Explorer API is the easiest free way to search 990 data by name or EIN.
  • England and Wales: the Charity Commission has its own register API. You sign up on their developer portal for a free subscription key.
  • Canada: the CRA publishes the list of charities and the T3010 returns on the Open Government Portal. They come as separate CSV files that you join on the Business Number, and they are refreshed once a year.
  • Australia: the ACNC publishes its charity register as open data on data.gov.au.

This works well until you need a second country. Then you are maintaining several pipelines, each with its own update schedule, its own column names, and its own idea of what a missing value looks like.

There are also the well-known US aggregators: the Candid API (formerly GuideStar) and the Charity Navigator API. Both are solid for US nonprofits, and both focus on the US.

Option 2: one API across 100+ countries

GiveRadar pulls the registers together: 7.9M+ nonprofit records across 100+ countries, from the national regulator or tax authority in most countries. Some countries have only a curated directory as a source, and we label those as such. You can see which registry feeds each country.

You need an API key (the free tier gives 10 requests a day, which is enough to try everything below). Then:

Search by name, optionally per country:

curl -H "Authorization: Bearer $GIVERADAR_API_KEY" \
  "https://giveradar.com/api/v1/search/?q=oxfam&country=GB&limit=5"
Enter fullscreen mode Exit fullscreen mode

Get one full profile by its slug:

curl -H "Authorization: Bearer $GIVERADAR_API_KEY" \
  "https://giveradar.com/api/v1/charity/oxfam-202918/"
Enter fullscreen mode Exit fullscreen mode

Look up a registration number. This one runs through the MCP endpoint, because that is where the registry lookup lives. It is plain JSON-RPC over HTTP, so curl is fine:

curl -X POST https://giveradar.com/mcp/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $GIVERADAR_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"verify_charity",
                 "arguments":{"country":"GB","id_value":"202918"}}}'
Enter fullscreen mode Exit fullscreen mode

The tool result is a JSON string inside result.content[0].text. Unpacked, it looks like this:

{
  "matches": [{
    "slug": "oxfam-202918",
    "name": "OXFAM",
    "registration_number": "202918",
    "ein": null,
    "uk_charity_number": "202918",
    "city": "Oxford",
    "state": "England",
    "integrity_score": 81,
    "url": "https://giveradar.com/charity/oxfam-202918/"
  }],
  "count": 1
}
Enter fullscreen mode Exit fullscreen mode

The same call works with "country": "US" and an EIN, or with the national registration number in other countries. That is the part I find most useful in practice: a charity number lookup that doesn't require a separate integration per country.

A small Python helper

import json
import os

import requests

KEY = os.environ["GIVERADAR_API_KEY"]
HEADERS = {"Authorization": f"Bearer {KEY}"}


def verify(country: str, number: str) -> list[dict]:
    """Return the organizations registered under `number` in `country`."""
    body = {
        "jsonrpc": "2.0", "id": 1, "method": "tools/call",
        "params": {"name": "verify_charity",
                   "arguments": {"country": country, "id_value": number}},
    }
    r = requests.post("https://giveradar.com/mcp/", json=body,
                      headers=HEADERS, timeout=30)
    r.raise_for_status()
    data = r.json()
    if "error" in data:
        raise RuntimeError(data["error"]["message"])
    return json.loads(data["result"]["content"][0]["text"])["matches"]


for country, number in [("GB", "202918"), ("US", "131624100")]:
    for m in verify(country, number):
        print(country, number, "->", m["name"], m["integrity_score"])
Enter fullscreen mode Exit fullscreen mode

If you would rather not write the plumbing, there is also a small client on PyPI (pip install giveradar, source on GitHub) with search(), charity(), verify() and a CLI.

Everything is documented in the API reference, including an OpenAPI spec you can feed to a code generator.

Free key vs Pro key

I want to be upfront about this. A free key returns the profile: name, country, category, registry IDs, website, red flags and the integrity score. Revenue, expenses, officers, executive pay and contact details are null on a free key. Those need Pro, which is $99 a month for 10,000 requests a day. The free tier is really a test allowance.

Option 3: no code at all

If you work in spreadsheets, Clay or n8n, I published the same lookups as an Apify Actor: Charity & Nonprofit Lookup on Apify. You paste a list of names, slugs or GB:202918-style registration numbers, add your own GiveRadar key, and download the result as CSV or Excel. It runs on your own key and quota, so nothing is stored anywhere except your run's dataset.

Option 4: let your AI agent do it

GiveRadar's MCP server exposes four tools: search_charities, compare_charities, find_similar and verify_charity. In Claude Code, it is one line:

claude mcp add giveradar --transport http https://giveradar.com/mcp/
Enter fullscreen mode Exit fullscreen mode

For Claude Desktop, add this to claude_desktop_config.json and restart:

{
  "mcpServers": {
    "giveradar": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://giveradar.com/mcp/"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Then you can just ask "what is registered under GB charity number 202918, and what is its integrity score?" and the agent calls verify_charity itself.

What the integrity score is, and what it is not

Every profile carries a 0 to 100 integrity score. It adds up five components: Registration (up to 20 points), Financial Transparency (30), Governance (20), Contact Availability (10), and Data Recency (20), minus a deduction for active red flags. The red flags are high executive pay, stale filings and bare-minimum disclosure.

It measures what a charity discloses. It doesn't measure impact, and it isn't a verdict on whether you should donate. A small, volunteer-run charity with a thin filing can score lower than a large one with a full annual report, and that says more about disclosure than about the quality of its work. If you show the score to users, I would show that context with it. Here is how the integrity score is put together, including what it leaves out.

Limits worth knowing before you build on it

  • Search matches on the name, needs at least 3 characters, and returns at most 100 results per query. There is no pagination, so it is built for lookups and enrichment, not for downloading entire registers.
  • Coverage differs per country. Some registers publish full financials (the US, England and Wales, Canada, Australia), others publish little more than a name and a number.
  • Registers update on their own schedule. The data is as fresh as the last import for that country, and each profile shows when it was last updated.
  • Commercial and public uses need to credit GiveRadar, and the raw data cannot be resold as your own dataset.

What you can do with data like this

Once the registers sit in one shape, you can compare them. One example: following the same charities through four years of filings in six registers, the share spending more than their income rose in all six between FY2021 and FY2024. That write-up on deficits and income concentration across six registers is built on exactly this data.

Or something much smaller: a form field that checks a Canadian Business Number on blur. You can browse Canadian charities on GiveRadar to see what a country looks like in the data.

If you are building something with charity data, I would love to hear what you need and which country is missing or thin. Leave a comment, or reach me at info@giveradar.com.

I drafted this post with the help of an AI assistant. The code samples and numbers were checked against the live API before publishing.

Top comments (0)