← Back to recipes

Find relevant grants automatically

fundraisingadvancedemerging

The problem

There are thousands of grants out there, but finding the right ones is painful. Keyword searches miss opportunities because funders use different language. You end up manually browsing databases, reading irrelevant listings, and probably missing grants that would have been perfect.

The solution

You'll set up an automated system that compares what you do (described in your own words) against grant opportunities using semantic matching. This means 'youth mentoring' matches 'supporting young people' even though the words are different. The system checks grant databases regularly and surfaces the best matches for you to review.

What you get

A weekly (or daily) email or spreadsheet with the top grant matches for your programmes. Each match includes the funder, deadline, typical amount, and why it matched. You review 10-15 relevant opportunities instead of searching through hundreds of irrelevant ones.

Before you start

  • Clear descriptions of your programmes (2-3 paragraphs each)
  • An OpenAI API key for generating embeddings
  • Access to a grants database you can export or query (360Giving is free)
  • Comfort with Python or help from someone who is
  • Ideally, time to maintain and update the system periodically

When to use this

  • You apply for grants regularly and want to find more opportunities
  • You've got multiple programmes to match against different funders
  • You're missing opportunities because keyword search isn't finding them
  • You want to be proactive about fundraising rather than reactive

When not to use this

  • You only apply for 2-3 grants a year. Manual search is fine
  • You already have a grants database subscription with good search. Use that first
  • You don't have capacity to review and act on more opportunities
  • Your funding comes mainly from one or two long-term funders you already know

Steps

  1. 1

    Write clear programme descriptions

    For each programme you want to fund, write 2-3 paragraphs: what you do, who benefits, what outcomes you achieve, where you work. Use plain language, not jargon. These descriptions are what the system matches against grant criteria. The better these are, the better your matches.

  2. 2

    Get grant data from 360Giving or another database

    360Giving GrantNav lets you export grants data for free. Download grants relevant to your sector and geography. You need: funder name, grant programme name, description/criteria, typical amount, deadline (if available), and a link. Start with a few hundred grants to test the system.

  3. 3

    Create embeddings for programmes and grants

    Embeddings are numerical representations of text that capture meaning. Similar concepts have similar embeddings. Use the OpenAI API to create embeddings for your programme descriptions and each grant's criteria. The example code shows how.

  4. 4

    Find the closest matches

    Compare your programme embeddings against all the grant embeddings. The closest matches are grants whose criteria are semantically similar to what you do. Rank them by similarity score and look at the top 10-20 for each programme.

  5. 5

    Review and filter the matches

    Not every match will be relevant. Check the top matches manually: is the geography right? Are you the right size of organisation? Is the deadline feasible? After reviewing, you'll learn what similarity score threshold works for your data.

  6. 6

    Set up regular matching(optional)

    Once the system works, run it regularly against fresh grant data. You could export new grants weekly, re-run the matching, and email yourself the top new opportunities. This turns grant-finding from a chore into a routine that surfaces opportunities automatically.

Example code

Create embeddings and find matches

This creates embeddings for your programmes and grants, then finds the best matches using cosine similarity.

import pandas as pd
from openai import OpenAI
import numpy as np

client = OpenAI()  # Uses OPENAI_API_KEY environment variable

# Your programme descriptions
programmes = [
    {
        "name": "Youth Mentoring",
        "description": """One-to-one mentoring for young people aged 14-19 who are
        at risk of exclusion from school. Trained volunteer mentors meet weekly
        for at least 6 months, helping with goal-setting, confidence building,
        and navigating challenges. We work across London with schools and
        youth organisations. Outcomes include improved attendance, better
        relationships with teachers, and clearer future plans."""
    },
    # Add more programmes
]

# Load grants from your export
grants = pd.read_csv('grants.csv')

def get_embedding(text):
    """Get embedding vector for text."""
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=text[:8000]  # Truncate if too long
    )
    return np.array(response.data[0].embedding)

def cosine_similarity(a, b):
    """Calculate similarity between two vectors (0 to 1)."""
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# Create embeddings for all programmes
print("Creating programme embeddings...")
for prog in programmes:
    prog['embedding'] = get_embedding(prog['description'])

# Create embeddings for all grants
print("Creating grant embeddings (this may take a few minutes)...")
grants['embedding'] = grants['description'].apply(get_embedding)

# Find best matches for each programme
print("\nFinding matches...")
for prog in programmes:
    print(f"\n=== Top matches for {prog['name']} ===\n")

    # Calculate similarity to all grants
    similarities = grants['embedding'].apply(
        lambda x: cosine_similarity(prog['embedding'], x)
    )

    # Get top 15 matches
    top_indices = similarities.nlargest(15).index

    for idx in top_indices:
        grant = grants.loc[idx]
        score = similarities[idx]
        print(f"{score:.0%} match - {grant['funder']}")
        print(f"  {grant['programme_name']}")
        print(f"  Amount: {grant.get('typical_amount', 'Not specified')}")
        print(f"  Link: {grant.get('url', 'N/A')}\n")

Tools

Google Colabplatform · freemium
Visit →
OpenAI APIservice · paid
Visit →
360Giving GrantNavplatform · free · open source
Visit →

Resources

At a glance

Time to implement
weeks
Setup cost
low
Ongoing cost
low
Cost trend
decreasing
Organisation size
small, medium
Target audience
fundraising, ceo-trustees, it-technical

API costs are minimal (a few pence per matching run). The main investment is setup time. Some grants databases require subscriptions (£100-500/year) but 360Giving is free.

Part of this pathway