# Shelter Pet Finder - Adoptable Dogs, Cats and More (`marielise.dev/shelter-pet-finder`) Actor

Adoptable dogs, cats, rabbits and more near any location, with photos, breed, age, sex, size, kids/dogs/cats compatibility and shelter contact. UK, Ireland, France, Germany, Italy, Spain, Taiwan, Japan and Singapore with no keys; US, Canada and Korea via free API keys (beta).

- **URL**: https://apify.com/marielise.dev/shelter-pet-finder.md
- **Developed by:** [Marielise](https://apify.com/marielise.dev) (community)
- **Categories:** Other, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 animal 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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Shelter Pet Finder

Find **adoptable shelter animals near a location** with everything a matching app needs: photos, breed, age, sex, size, whether the animal can live with children, dogs or cats, a full description, the listing URL, and the shelter's contact details. Dogs and cats by default; rabbits, guinea pigs, hamsters, ferrets, birds, reptiles, fish, horses and farm animals where a source lists them. Optionally add the **shelters and rescues** around that location too.

Built for people looking for their next pet and for developers building adoption search, matchmaking or rescue-support products. Covers the UK, Ireland, France, Germany, Italy, Spain, Portugal, Taiwan, Japan and Singapore with no keys, plus South Korea, the US and Canada with free API keys.

### What you get

Each animal is one dataset item with a stable `id` (`source:externalId`), so you can re-run the actor and diff results to spot new arrivals, changed listings (`contentHash`) and animals that have gone (missing from the next run).

| Field group | Fields |
|-------------|--------|
| Identity | `id`, `externalId`, `source`, `species`, `name`, `url`, `status` (available, reserved), `listedAt` |
| Looks | `breed`, `breedPrimary`, `breedSecondary`, `isMixed`, `size`, `sex`, `coat`, `colors` |
| Age | `ageText`, `ageMonths`, `ageBucket` (puppy, young, adult, senior) |
| Home fit | `goodWithKids`, `goodWithKidsMinAge`, `goodWithDogs`, `goodWithCats`, `houseTrained`, `specialNeeds`, `energyLevel`, `temperamentTags` |
| Health | `neutered`, `vaccinated` |
| Media | `images` (full-size URLs, primary first), `primaryImage`, `videos` |
| Shelter | `shelterId`, `shelterName`, `shelterUrl`, `shelterPhone`, `shelterEmail`, `location`, `country`, `coordinates`, `distanceKm` |
| Money | `adoptionFee` |
| Bookkeeping | `contentHash`, `scrapedAt` |

Animal records carry `recordType: "animal"` and a normalised `species` (`dog`, `cat`, `rabbit`, `small-furry`, `bird`, `reptile`, `fish`, `horse`, `farm`, `other`). Shelter records share the same shape with `recordType: "shelter"` and carry `googleMapsRating`, `googleMapsReviews`, `needsVolunteers`, `needsDonations` and `urgencySignals`.

### Sources and coverage

| Region | Source | Species | Needs | What it returns |
|--------|--------|---------|-------|-----------------|
| UK | **Dogs Trust** | dogs | nothing | All dogs nationally via the site's search API, filtered to centres within your radius. 800x600 photos, compatibility by child age band, reserved flag. |
| UK | **Battersea** | dogs, cats | nothing | Every animal at London, Old Windsor and Brands Hatch with sex, size, living-with flags, photos, full write-up. |
| UK | **RSPCA** | dogs, cats, rabbits, small furries, birds, reptiles, horses, farm | nothing | The 50 nearest animals per species from the RSPCA pet search, with branch contact, colour, photos and description. |
| Ireland | **Dogs Trust Ireland** | dogs | nothing | Same API as the UK site. |
| France, Germany, Italy, Spain, UK | **Wamiz** | dogs, cats | nothing | Shelter and association listings through Wamiz's JSON search API (about 4,400 dogs and 4,000 cats in France, 3,700 dogs in Germany). Photos, sex, age, size, neutered, vaccinated, fee, shelter address and coordinates. |
| France | **Seconde Chance** | dogs, cats, rabbits, small furries, horses, farm, birds, reptiles, fish | nothing | France's largest refuge aggregator (about 12,000 dogs alone), searched by the departments around your location. Exact birth date, breed, sex, size, coat, gallery, full write-up and the refuge's address, email and phone. |
| Germany | **Tierheimhelden** | dogs, cats, rabbits, small furries, birds, reptiles, horses, farm, fish | nothing | Animals from German shelters and rescues within up to 100 km of a postcode. Birth date, breed, size, sex, neutered, house-trained, good with children, dogs and cats, gallery, full write-up. |
| Portugal | **Pawseum** | dogs, cats | nothing | Dogs and cats from Portuguese shelters and municipal kennels (about 760 available across 40+ kennels). Birth date, breed, size, sex, colours, temperament tags, neutered, vaccinated, kennel phone and email. Only kennel listings are read, never private owners. |
| Taiwan | **MOA open data** | dogs, cats, other | nothing | Every animal in a public shelter (about 8,400), with sex, size, age band, colour, neutered, vaccinated, photo, shelter address and phone. Shelter coordinates are geocoded and cached. |
| Japan | **pet-home.jp** | dogs, cats, small furries, birds, reptiles, fish | nothing (browser) | Listings open to adopters in the searched prefecture: photos, breed, sex, age, size, vaccination, neutering, fee, rescue group name and full write-up. |
| Singapore | **SPCA Singapore** | dogs, cats, rabbits, small furries, reptiles, other | nothing | Everything on spca.org.sg with breed, sex, colour, age, sterilised flag, personality, training and gallery. |
| South Korea | **animal.go.kr open API** | dogs, cats, other | free data.go.kr key (beta) | Every animal in care nationally with up to 8 photos, breed, sex, age, weight, neutered, colour, shelter address and phone. |
| US, Canada, Mexico | **Petfinder API** | 8 types | free key and secret (beta) | Adoptable animals within the radius with photos, attributes, environment flags, tags and organisation contact. |
| US, Canada | **RescueGroups API** | 8 types | free key (beta) | Animals with pictures within the radius, including energy level, house-training and fee. |
| anywhere | **Google Maps** (optional) | shelters | billed by that actor, about $0.004 per place | Shelters, rescues and animal-protection associations near the location. The fallback for countries without a listing platform (Netherlands, Poland, Nordics, most of South and Southeast Asia). |

Sources that do not cover the searched country are skipped automatically and reported in `RUN_SUMMARY`.

Sources marked beta are written against the official APIs but have not yet been verified with a live key. If one misbehaves, please open an issue.

### Input

```json
{
  "location": "London",
  "species": ["dog", "cat"],
  "radiusKm": 50,
  "searchMode": "adopt",
  "goodWithKids": false,
  "includeReserved": false,
  "fetchDetails": true,
  "maxResults": 50
}
```

- `species`: defaults to dogs and cats. Leave empty for every species a source offers (`rabbit`, `small-furry`, `bird`, `reptile`, `fish`, `horse`, `farm`, `other`). Results are interleaved so one species cannot fill `maxResults`.
- `searchMode`: `adopt` (animals only, default), `support` (shelters only) or `both`.
- `includeReserved`: reserved and adoption-pending animals are dropped by default so results stay actionable.
- `fetchDetails`: opens each animal's page for the full description and all photos. Turn off for a faster, thinner crawl.
- `enableGoogleMaps` + `googleMapsMaxPlaces`: shelter discovery for `support` or `both` mode. Off by default because that actor has its own pricing.
- `petfinderApiKey`, `petfinderApiSecret`, `rescueGroupsApiKey`, `koreaApiKey`: stored as secrets, only used for those sources.
- `exportStoreName` + `exportKey`: also save the results to a named key-value store under a fixed key, so an app can always read the latest list from one URL (`https://api.apify.com/v2/key-value-stores/<store>/records/<key>`). Pair with a schedule for a self-refreshing feed.

### Output

- **Dataset**: one item per animal or shelter, sorted by distance. Views: *Nearby animals* and *Shelters*.
- **Key-value store**: `RUN_SUMMARY` (per-source status, counts and warnings), `OUTPUT.json`, `adoption_results.csv`, `REPORT.md`.

A run always succeeds even if one source is down; check `RUN_SUMMARY.sourceOutcomes` for `blocked`, `failed` or `empty` sources.

Example animal record (trimmed):

```json
{
  "recordType": "animal",
  "id": "dogstrust:3661543",
  "source": "dogstrust",
  "species": "dog",
  "name": "Hallie",
  "url": "https://www.dogstrust.org.uk/rehoming/dogs/chihuahua-smooth-coat/3661543",
  "status": "available",
  "listedAt": "2026-09-20T16:58:12.000Z",
  "breed": "Chihuahua (Smooth Coat)",
  "isMixed": false,
  "ageText": "7 years, 6 months",
  "ageMonths": 90,
  "ageBucket": "adult",
  "size": "small",
  "sex": "female",
  "specialNeeds": true,
  "goodWithKids": true,
  "goodWithKidsMinAge": "primary",
  "goodWithDogs": false,
  "goodWithCats": false,
  "images": ["https://www.dogstrust.org.uk/images/800x600/dogs/3661543/068Tf00000fh587IAA.jpg"],
  "shelterName": "Dogs Trust Harefield West London",
  "shelterPhone": "0303 003 0000",
  "coordinates": { "lat": 51.58442, "lng": -0.47125 },
  "distanceKm": 25.3
}
```

### Pricing

Pay per event. You pay only for what the run does, and platform usage is included.

| Event | Price | When |
| --- | --- | --- |
| Actor start | $0.02 per GB of memory ($0.08 at the default 4 GB) | Once per run |
| Source searched | $0.02 | Each source that actually ran (blocked, failed or skipped sources are free) |
| Animal result | $0.002 ($2 per 1,000) | Each adoptable animal saved to the dataset |
| Shelter result | $0.005 | Each shelter saved to the dataset (Google Maps discovery) |

Examples:

- London, dogs and cats, 50 results from 4 UK sources (the default input): about $0.26. With 300 results: about $0.76.
- Paris, 100 results from Wamiz: about $0.30.

Set **Max total charge** on the run to cap spend. The actor stops starting new sources and saves only the records the cap allows. Google Maps discovery also starts a separate `compass/crawler-google-places` run, which has its own pricing.

### Keeping a feed fresh

- Re-run per region on a schedule (UK sources are cheap plain HTTP; every few hours is fine).
- Check `schemaVersion` (currently `1`) before ingesting; it only changes when the record shape breaks.
- Key your database on `id`. An animal present in the previous run and missing from the current one has most likely been rehomed.
- Compare `contentHash` to detect edited listings without diffing every field.
- `status: "reserved"` animals are still listed by the shelter but not available; include them with `includeReserved` if you want to show "reserved" badges.

### Notes on sources

- pet-home.jp lists animals by the prefecture they can be adopted into, so the radius filter is not applied there; `distanceKm` still tells you how far the animal currently is.
- RSPCA pins one species per session, so each species is searched in its own browser context. Requesting all ten takes roughly three minutes.
- Taiwan and Korea listings have no per-animal page; `url` points at the shelter search and `externalId` is the animal's registry number.
- The first Taiwan or Korea run geocodes every shelter address (about one per second); later runs reuse the `dog-shelter-finder-geocache` store.
- Petfinder's website blocks automated access; this actor uses the official API only.
- Adopt-a-Pet is not scraped (geo-blocked and against its terms); RescueGroups exposes much of the same inventory through a free API.
- Placeholder images ("no image available") are dropped, so an empty `images` array means the shelter published no photo.
- Dogs Trust, Battersea and RSPCA are charities. The actor keeps request rates low and only reads public listing pages.

### Use cases

- **Adoption and matching apps**: a location-aware feed of adoptable animals with photos and compatibility flags, keyed for daily sync.
- **Rescue support tools**: find shelters near a place and which of them ask for volunteers or donations (`searchMode: "support"`).
- **Research and reporting**: shelter populations by species, age and region over time.
- **Alerts**: schedule a run and notify adopters when a new animal matching their filters appears.

### FAQ

**Why did my run return a `status` record instead of animals?**
When no animal or shelter could be saved, the run stores one `recordType: "status"` item per source saying what happened (`blocked`, `failed`, `skipped` or `empty`). Status records are never charged.

**Why is a source missing from my results?**
Each source covers specific countries. The rest are skipped for your location, and are listed with a reason in `RUN_SUMMARY` in the key-value store.

**Can I get every animal in a country?**
Set a large `radiusKm` (up to 500) and a high `maxResults`. For a full national feed, run once per region on a schedule and key your database on `id`.

**How fresh is the data?**
Every run reads the live listings. Animals are rehomed quickly, so re-run at least daily for a production feed.

**How do I keep costs down?**
Lower `maxResults`, pick only the `sources` you need, and set a **Max total charge** on the run.

### Legal and data use

- **Photos and descriptions** belong to the shelters and posters. The actor returns image URLs only and never rehosts images. Link back to the listing (`url`) when you display an animal.
- **Personal data.** The actor collects organisation contact details, not details about individuals. pet-home.jp poster names are kept only when they read as an organisation. Google review text is reduced to tags such as `overcrowded`.
- **Open data.** Taiwan's government open data is published under the Open Government Data License 1.0, which requires attribution. Korean data comes from the data.go.kr API under that portal's terms of use.
- **Pawseum** publishes a documented public API; its robots.txt nonetheless disallows `/api/`. The actor reads kennel rosters only, one request per nearby kennel.
- **Seconde Chance** asks crawlers for one request per second; the actor follows that.
- **pet-home.jp** is protected by an anti-bot check that the actor passes with a real browser. Review that site's terms before using its data commercially.
- **Your responsibility.** You are responsible for complying with each source's terms of use and with privacy law (for example GDPR) in how you store and use the results.

# Actor input Schema

## `location` (type: `string`):

City, town, postcode or region to search around. Examples: "London", "Paris", "Berlin", "Dublin", "Taipei", "Tokyo", "Singapore", "Austin, TX".

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

Which animals to include. Leave empty for every species a source offers. Sources that do not list a requested species are skipped.

## `radiusKm` (type: `integer`):

Animals and shelters further than this from the location are dropped.

## `country` (type: `array`):

Optional ISO 3166-1 alpha-2 codes to restrict sources. Usually inferred from the location.

## `searchMode` (type: `string`):

Adoptable animals only, shelters only, or both record types in one dataset.

## `sources` (type: `array`):

Adoption platforms to query. Leave empty for all. Sources outside the searched country are skipped automatically.

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

Upper bound on records returned across all sources. Results are interleaved across species so one species cannot fill the cap. Each result is charged, so this also bounds the cost of a run.

## `breed` (type: `array`):

Keep animals whose breed contains any of these words, e.g. labrador, lurcher, tabby.

## `ageMax` (type: `integer`):

Drop animals older than this. Animals with unknown age are kept.

## `size` (type: `string`):

Preferred size. Applies to species that report one; animals with unknown size are kept.

## `goodWithKids` (type: `boolean`):

Only animals explicitly marked as able to live with children.

## `goodWithDogs` (type: `boolean`):

Only animals explicitly marked as able to live with dogs.

## `goodWithCats` (type: `boolean`):

Only animals explicitly marked as able to live with cats.

## `includeReserved` (type: `boolean`):

Keep animals that are reserved or have an adoption pending. Off by default so results are actionable.

## `fetchDetails` (type: `boolean`):

Open each animal's page for the full description, all photos and compatibility flags. Slower but much richer.

## `petfinderApiKey` (type: `string`):

Free key from petfinder.com/developers. Required for the petfinder source (US, CA, MX). Beta: this source has not been verified with a live key yet.

## `petfinderApiSecret` (type: `string`):

Secret paired with the Petfinder API key.

## `rescueGroupsApiKey` (type: `string`):

Free key from rescuegroups.org (Adoptable Pet Data API). Required for the rescuegroups source (US, CA). Beta: this source has not been verified with a live key yet.

## `koreaApiKey` (type: `string`):

Free key from data.go.kr for service 15098931 (abandonmentPublicService\_v2). Required for the korea-gov source. Beta: this source has not been verified with a live key yet.

## `enableGoogleMaps` (type: `boolean`):

Run compass/crawler-google-places to find local shelters and rescues, including ones with no listing platform. That actor has its own pricing (about $0.004 per place). Only used when search mode includes shelters.

## `googleMapsMaxPlaces` (type: `integer`):

Cap on places pulled from Google Maps per run.

## `exportStoreName` (type: `string`):

Optional. Also saves the results to this named key-value store in your account, so an app can always read the latest list from one fixed URL. Letters, digits and hyphens.

## `exportKey` (type: `string`):

Record key inside the export store, e.g. the city name. Defaults to LATEST. Each run overwrites it; a run with no results leaves it unchanged.

## Actor input object example

```json
{
  "location": "London",
  "species": [
    "dog",
    "cat"
  ],
  "radiusKm": 50,
  "country": [],
  "searchMode": "adopt",
  "sources": [
    "dogstrust",
    "battersea",
    "rspca",
    "wamiz",
    "petfinder",
    "rescuegroups",
    "taiwan-gov",
    "pet-home-jp",
    "korea-gov",
    "spca-sg",
    "pawseum",
    "secondechance",
    "tierheimhelden"
  ],
  "maxResults": 50,
  "breed": [],
  "size": "any",
  "goodWithKids": false,
  "goodWithDogs": false,
  "goodWithCats": false,
  "includeReserved": false,
  "fetchDetails": true,
  "enableGoogleMaps": false,
  "googleMapsMaxPlaces": 30
}
```

# Actor output Schema

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

Every record, closest first

## `shelters` (type: `string`):

Shelter and rescue organisation records view

## `keyValueStore` (type: `string`):

Actor run key-value store for CSV, report, and JSON outputs

## `nearbyAnimals` (type: `string`):

Animal records view

# 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 = {
    "location": "London",
    "species": [
        "dog",
        "cat"
    ],
    "radiusKm": 50,
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("marielise.dev/shelter-pet-finder").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 = {
    "location": "London",
    "species": [
        "dog",
        "cat",
    ],
    "radiusKm": 50,
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("marielise.dev/shelter-pet-finder").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 '{
  "location": "London",
  "species": [
    "dog",
    "cat"
  ],
  "radiusKm": 50,
  "maxResults": 50
}' |
apify call marielise.dev/shelter-pet-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,marielise.dev/shelter-pet-finder"
        }
    }
}
```

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/6fqC6PbSLbhMX8HY5/builds/tl4gcdHV8opQVezMM/openapi.json
