# WalletHub Rankings Scraper (`crawlerbros/wallethub-scraper`) Actor

Scrape WalletHub.com's data-driven state/city ranking studies - personal finance, economy, health, safety and lifestyle rankings. Fetch any ranking study's full ranked table by URL, pick from 40+ curated popular studies, or browse the latest published studies.

- **URL**: https://apify.com/crawlerbros/wallethub-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Developer tools, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## WalletHub Rankings Scraper

Scrape [WalletHub.com](https://wallethub.com)'s data-driven state and city ranking studies — personal finance, economy, health, safety, education, and lifestyle rankings, each backed by a scored, ranked table of 50 states or 100+ cities. Fetch any study by URL, pick from 40+ curated popular studies, or browse the latest published studies. No login, no cookies, no proxy required.

### What this actor does

- **Two modes:** `ranking` (full ranked table for one or more studies) and `latestStudies` (browse the newest published studies)
- **40+ curated topics** via a dropdown, plus free-form `rankingUrls` for any WalletHub `/edu/...` study
- **Filters:** rank range, entity-name (state/city) keyword
- **Every study's category columns preserved** — sub-rank and sub-score columns are auto-flattened into camelCase fields
- **Optional methodology, metric highlights, expert panel, related studies & reader Q\&A** (`includeMethodology`) — one extra record per study with the scoring-criteria breakdown (categories, weights, metrics), the "Metric Highlights" info-graphic (each underlying metric's own top-5/bottom-5 states plus a best-vs-worst headline, e.g. "2x Difference"), the "Ask the Experts" panelist list (name, credentials, photo), the "You May Also Like" related-study links (title, URL, image), and the reader-submitted "Questions & Answers" list (question, URL, upvote count)
- **Empty fields are omitted**

### Output per ranking entry (mode=ranking)

- `studyTitle`, `studyUrl`, `studyId`, `studyYear`
- `studyAuthor` — WalletHub analyst credited for the study
- `studyAuthorImageUrl` — the credited analyst's headshot photo
- `studyAuthorProfileUrl` — link to the analyst's WalletHub profile page
- `studyPublishedDate` — the study's publish date as shown on the page (e.g. `"Jul 27, 2026"`)
- `studyModifiedDate` — the study's last-updated date as shown on the page
- `studyImageUrl` — the study's hero/cover image
- `entityName` — state or city name
- `rank` — overall rank (1 = best)
- `totalScore` — overall weighted score
- Study-specific sub-rank/sub-score columns, auto-named from the study's own table headers (e.g. `costRank`, `accessRank`, `outcomesRank`)
- `sizeCategory` — only present for multi-category studies that publish separate side-by-side rank/score tables per group (e.g. "Best Cities for First-Time Home Buyers" ranks Large/Midsize/Small cities separately); `rank` is then relative to that category, not the whole study
- `sourceUrl`, `recordType: "rankingEntry"`, `scrapedAt`

### Output per methodology record (mode=ranking, `includeMethodology: true`)

One extra record per study (not per entity):

- `studyTitle`, `studyUrl`, `studyId`
- `methodology` — array of `{category, totalPoints, metrics: [{name, weight, note}]}` (WalletHub's own scoring-criteria breakdown)
- `metricHighlights` — array of `{metricName, imageUrl, bestLabel, bestStates: [{rank, name}, ...], worstLabel, worstStates: [{rank, name}, ...], bestState, worstState, difference}` (WalletHub's "Metric Highlights" info-graphic: each underlying metric's own top-5/bottom-5 states, independent of the study's overall ranking, plus a best-vs-worst headline like "2x Difference")
- `expertPanel` — array of `{name, credentials, imageUrl}` (the "Ask the Experts" panelists WalletHub features on the study)
- `relatedStudies` — array of `{title, url, imageUrl}` (the "You May Also Like" related-study recommendations WalletHub shows on the study page)
- `readerQuestions` — array of `{question, url, upvotes}` (WalletHub's reader-submitted "Questions & Answers" widget for the study; answer bodies are loaded client-side by WalletHub and are not included)
- `sourceUrl`, `recordType: "methodology"`, `scrapedAt`

### Output per study (mode=latestStudies)

- `studyTitle`, `studyUrl`, `studyId`, `studyYear`
- `sourceUrl`, `recordType: "study"`, `scrapedAt`

Note: `mode=latestStudies` reads WalletHub's single latest-awards hub page, which lists roughly 100 studies with no further pagination. Setting `maxItems` above that count will not yield more records -- the run simply returns everything the hub page has.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `ranking` | `ranking` / `latestStudies` |
| `topic` | select | Healthcare study | Curated popular study (mode=ranking) |
| `rankingUrls` | array | – | Custom WalletHub `/edu/...` study URLs (mode=ranking) |
| `minRank` | int | – | Drop entries ranked better than this |
| `maxRank` | int | – | Drop entries ranked worse than this |
| `entityNameContains` | string | – | State/city name must contain this substring |
| `includeMethodology` | boolean | `false` | Emit one extra methodology + expert-panel + related-studies record per study (mode=ranking) |
| `maxItems` | int | `200` | Hard cap on emitted records (1–1000) |

#### Example: top 10 states for healthcare

```json
{
  "mode": "ranking",
  "topic": "https://wallethub.com/edu/states-with-best-healthcare/23457",
  "maxRank": 10
}
```

#### Example: multiple custom studies in one run

```json
{
  "mode": "ranking",
  "topic": "",
  "rankingUrls": [
    "https://wallethub.com/edu/best-states-for-jobs/35641",
    "https://wallethub.com/edu/greenest-states/11987"
  ]
}
```

#### Example: browse the latest published studies

```json
{
  "mode": "latestStudies",
  "maxItems": 100
}
```

### Limitations

- WalletHub blocks Apify's raw datacenter egress IP with a 403 on the first request. The actor automatically engages Apify Proxy's free `AUTO` group (no residential proxy required, no extra cost) as soon as it sees a 403, then reuses that session for the rest of the run.
- Only WalletHub `/edu/...` study pages that publish a ranked data table are supported by `mode=ranking`; a small number of `/edu/...` pages are pure explainer articles with no table and will emit 0 records for that URL.
- On rare occasions WalletHub's bot-mitigation serves a soft-blocked/interstitial page (HTTP 200, but no ranking table) to a specific `AUTO`-group datacenter exit IP for a specific study, even though the very same URL parses correctly on a plain, non-proxied fetch. The actor automatically rotates to a fresh proxy session and retries once before giving up on that URL; if it still can't find a table after the retry, that URL is skipped (logged as a warning) and the run continues with any other requested studies rather than failing the whole run.

### Use cases

- **Personal finance content** — pull ranked state/city data for articles and comparison tools
- **Relocation & real-estate research** — compare states/cities on affordability, safety, or job-market rankings
- **Market research** — track how a state/city ranks across dozens of WalletHub studies
- **Data journalism** — bulk-export ranking tables for visualization
- **Lead generation for local businesses** — target markets ranked highly for relevant categories (e.g. "best cities to start a business")

### FAQ

**Do I need a WalletHub account?**  No — all data comes from WalletHub's free public study pages.

**What if my study isn't in the `topic` dropdown?**  Leave `topic` empty (select "Custom URL(s) below") and paste the study's URL into `rankingUrls`.

**Why do column names vary between studies?**  Each WalletHub study defines its own sub-rank categories (e.g. "Cost Rank" for healthcare, "Opportunity & Competition Rank" for teachers). The actor auto-converts each study's own table headers into camelCase fields, so you get exactly the columns that study publishes — no invented or missing categories.

**Are city-level and state-level studies both supported?**  Yes — `entityName` holds whichever the study ranks (state or city); the actor detects the entity column automatically.

**How current is the data?**  WalletHub republishes most studies annually (the year appears in `studyYear`/`studyTitle` when the source includes it); the actor always scrapes the current live page, not a cached snapshot.

**Can I get every WalletHub study, not just the curated 40?**  Yes — use `rankingUrls` with any `/edu/...` link, or run `mode=latestStudies` first to discover current study URLs, then feed those into `mode=ranking`.

**Why did I get 0 results?**  Either the study URL doesn't have a ranked data table (some WalletHub `/edu/` pages are pure explainer articles with no table), or `minRank`/`maxRank`/`entityNameContains` excluded every row. Widen the filters and retry.

# Actor input Schema

## `mode` (type: `string`):

What to fetch. Note: `latestStudies` reads WalletHub's single latest-awards hub page, which lists roughly 100 studies with no further pagination -- `maxItems` above that count will not yield more records.

## `topic` (type: `string`):

Pick a popular WalletHub ranking study. Leave as "Custom URL(s) below" and use `rankingUrls` to fetch any other study.

## `rankingUrls` (type: `array`):

Any WalletHub `/edu/...` ranking-study URLs. Combined with `topic` if both are set.

## `minRank` (type: `integer`):

Drop entries ranked better (lower number) than this.

## `maxRank` (type: `integer`):

Drop entries ranked worse (higher number) than this.

## `entityNameContains` (type: `string`):

Case-insensitive substring the state/city name must contain, e.g. `New`.

## `includeMethodology` (type: `boolean`):

Emit one extra `methodology` record per study with the scoring-criteria breakdown (categories, weights, metrics), the per-metric "Metric Highlights" (each underlying metric's own top-5/bottom-5 states plus a best-vs-worst headline, e.g. "2x Difference"), the "Ask the Experts" panelist list (name, credentials, photo), the "You May Also Like" related studies, and the reader Q\&A list.

## `maxItems` (type: `integer`):

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "ranking",
  "topic": "https://wallethub.com/edu/states-with-best-healthcare/23457",
  "rankingUrls": [],
  "includeMethodology": false,
  "maxItems": 100
}
```

# Actor output Schema

## `rankings` (type: `string`):

Dataset containing all scraped WalletHub ranking entries and/or studies.

# 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 = {
    "mode": "ranking",
    "topic": "https://wallethub.com/edu/states-with-best-healthcare/23457",
    "rankingUrls": [],
    "includeMethodology": false,
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/wallethub-scraper").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 = {
    "mode": "ranking",
    "topic": "https://wallethub.com/edu/states-with-best-healthcare/23457",
    "rankingUrls": [],
    "includeMethodology": False,
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/wallethub-scraper").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 '{
  "mode": "ranking",
  "topic": "https://wallethub.com/edu/states-with-best-healthcare/23457",
  "rankingUrls": [],
  "includeMethodology": false,
  "maxItems": 100
}' |
apify call crawlerbros/wallethub-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/wallethub-scraper"
        }
    }
}

```

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/4T9VeUMfoMtngUqRJ/builds/z14I95cIs0JZj2A8U/openapi.json
