Scrape Kickstarter as clean, structured JSON or CSV. You get project search with category, state, location, goal and funding filters, full project details with every reward tier and add-on, live funding counters, and a funding tracker that reports what changed since the last run. It ships as a CLI and a Node library.
Powered by ScrapeUnblocker. Every request goes through the ScrapeUnblocker
getPageSourceAPI with the official Node.js SDK, so you don't run browsers, manage proxies or get rate-limited from your own IP. The scraper reads the JSON Kickstarter itself uses (its discover search feed, the project object embedded in each project page, and small stats and location endpoints) instead of the visual markup, so there are no CSS selectors to maintain.
- 🔎 Project search: Kickstarter's discover index with free-text terms, any of its 15 categories and 154 subcategories, project state (live, successful, failed, upcoming), location (a city or a country, by name or ID), "Projects We Love" only, goal, pledged and percent-raised ranges, and all six sort orders (magic, popularity, newest, ending soon, most funded, most backed). You can fetch up to 200 pages of 12 projects per query. Rows are deduped, and you can pass several search terms at once.
- 📊 Clean project records: goal, pledged, percent funded, backers, average pledge, the USD conversion Kickstarter fixed for the campaign, launch date, deadline, duration, days left, category with its parent, creator, location with its ID, staff pick and late-pledge flags, and the image and video URLs.
- 🎁 Project details and rewards: comments and updates counts, tags, and every reward tier and add-on with its price, backers, quantity limit and remaining stock, estimated delivery month, shipping summary, availability window and included items.
- 📈 Funding tracker:
statsreads a tiny JSON endpoint with live backers, pledged amount and comments. With--historyit appends snapshots to a JSON Lines file and reports the change since the previous run, so a cron job can build funding curves for a watchlist. - 🗺️ Location lookup: turns "Berlin" into the location ID the search filter takes.
- 🗂️ Category list: ships offline, or you can refresh it live with
categories --live. - 📄 JSON, JSON Lines or CSV output. Nested values are flattened for CSV.
- 🔁 Retries with backoff on blocks, timeouts and incomplete responses. A real 404 is never retried.
Requires Node.js 18 or newer.
git clone https://github.com/ScrapeUnblocker/kickstarter-scraper.git
cd kickstarter-scraper
npm install
npm link # optional: puts `kickstarter-scraper` on your PATHGet an API key at
scrapeunblocker.com
and export it (or copy .env.example to .env and load it your usual way):
export SCRAPEUNBLOCKER_KEY=your_key_herekickstarter-scraper <command> [arguments] [options]
search [term...] Projects from Kickstarter's discover search (12 per page)
project <url...> Full project details: funding, creator, rewards, add-ons
rewards <url> One row per reward tier and add-on of a project
stats <url...> Live backers / pledged / comments (cheap, for tracking)
locations <place> Find the location ID for a city or country
categories List categories (no API call; --live to refresh)
<url> is a project URL (any tab, with or without ?ref= parameters) or a
creator/project-slug path. Run kickstarter-scraper --help to see every
option.
# The most-funded live board games, 3 pages, as CSV
kickstarter-scraper search -c "Tabletop Games" -s live --sort most_funded -p 3 -o games.csv
# Successful campaigns for two keywords with a $10k-$100k goal, most backed first
kickstarter-scraper search solar "e-bike" -s successful --goal 10k-100k --sort most_backed
# Staff-picked technology projects from Berlin
kickstarter-scraper search -c technology --location Berlin --staff-picks
# Campaigns ending soon that are already over 100% funded, with 500+ backers
kickstarter-scraper search -s live --sort end_date --raised over-100 --min-backers 500 -p 5
# Prelaunch pages in Video Games, newest first
kickstarter-scraper search -c "Video Games" -s upcoming --sort newest
# Full project details, and its reward tiers as CSV
kickstarter-scraper project https://www.kickstarter.com/projects/brotherwise/war-for-roshar
kickstarter-scraper rewards brotherwise/war-for-roshar -o rewards.csv
# Track a watchlist (one URL per line); each run reports the change since the last
kickstarter-scraper stats --from watchlist.txt --history funding.jsonl -f csv
# Location IDs and categories
kickstarter-scraper locations "New York"
kickstarter-scraper categories -o categories.csv| Option | Values |
|---|---|
-c, --category |
A name (Gadgets), a slug (technology/gadgets, games/tabletop-games) or an ID (337). Names that exist in several categories, such as "Comedy", ask you to pick a slug. |
-s, --state |
live, successful, failed, upcoming or all (default). Upcoming projects are prelaunch pages, with the state submitted or started. |
--sort |
magic (default), popularity, newest, end_date (alias ending-soon), most_funded, most_backed |
--goal, --pledged |
under-1k, 1k-10k, 10k-100k, 100k-1m, over-1m (USD) |
--raised |
under-75, 75-100, over-100 (percent of goal) |
--location |
A city or country name (the best match is used) or a location ID from locations |
-p, --pages / -l, --limit |
Pages per term (1-200) and maximum projects per term |
--min-backers, --min-percent |
Local filters applied after fetching |
-o, --out / -f, --format |
Output file and json, jsonl or csv (taken from the file extension by default) |
import { KickstarterScraper, toCsv, trackStats } from "kickstarter-scraper"; // or "./src/index.js" in a clone
const ks = new KickstarterScraper(); // reads SCRAPEUNBLOCKER_KEY
// Search: friendly filters, paging, dedupe
const games = await ks.search({
category: "Tabletop Games",
state: "live",
sort: "most_funded",
pages: 2,
});
console.log(games[0].name, games[0].percent_funded, games[0].days_left);
// Several terms with the same filters; each row gets the `term` that found it
const rows = await ks.searchTerms(["solar", "e-bike"], { state: "successful", goal: "10k-100k" });
// Full details with reward tiers and add-ons (null if the project does not exist)
const project = await ks.project("brotherwise/war-for-roshar");
for (const r of project.rewards) console.log(r.title, r.minimum, r.backers_count, r.remaining);
// Live counters for a watchlist, and the change since the previous snapshot
const changes = await trackStats("funding.jsonl", await ks.stats([project.url]));
// How many projects match a query, from one request
const failed = await ks.count({ category: "Gadgets", state: "failed" });
// Location IDs
const [berlin] = await ks.locations("Berlin"); // { id: 638242, name: "Berlin, Germany", ... }
console.log(toCsv(rows));Constructor options: apiKey, proxyCountry (default "US"), retries
(default 2), backoffMs (default 2000, doubles each retry), concurrency
(parallel requests for multi-project calls, default 4), log (a progress
callback) and client (inject a mock for tests).
kickstarter-scraper search -c "Tabletop Games" -s live --sort most_funded -l 1
(URLs shortened):
[
{
"id": 1878275683,
"name": "Stormlight: War for Roshar",
"blurb": "Command the forces of Honor and Odium in this strategic board game based on Brandon Sanderson's epic fantasy series!",
"state": "live",
"url": "https://www.kickstarter.com/projects/brotherwise/war-for-roshar",
"category": "Tabletop Games",
"category_slug": "games/tabletop games",
"category_id": 34,
"parent_category": "Games",
"creator": "Brotherwise Games",
"creator_id": 237961243,
"creator_slug": "brotherwise",
"creator_url": "https://www.kickstarter.com/profile/brotherwise",
"location": "Los Angeles, CA",
"location_id": 2442047,
"location_type": "Town",
"location_state": "CA",
"location_country": "US",
"country": "US",
"currency": "USD",
"currency_symbol": "$",
"goal": 100000,
"pledged": 2521276,
"percent_funded": 2521.3,
"backers_count": 10194,
"average_pledge": 247.33,
"usd_rate": 1,
"goal_usd": 100000,
"pledged_usd": 2521276,
"staff_pick": true,
"spotlight": false,
"late_pledges": false,
"created_at": "2026-05-17T00:19:05Z",
"launched_at": "2026-10-13T13:00:19Z",
"deadline": "2026-11-06T04:59:00Z",
"state_changed_at": "2026-10-13T13:00:23Z",
"duration_days": 23.7,
"days_left": 9.2,
"image_url": "https://i.kickstarter.com/assets/055/489/461/..._original.png?...",
"video_url": "https://v2.kickstarter.com/.../video-1467688-h264_high.mp4"
}
]project returns the same fields plus comments_count, updates_count,
tags, reward_count, add_on_count, rewards and add_ons. One reward
tier looks like this:
{
"id": 11415772,
"type": "base",
"title": "First Ideal",
"minimum": 90,
"currency": "USD",
"description": "Speak the words and receive the retail version of the base game along with all unlocked base game stretch goals.",
"backers_count": 211,
"limit": null,
"remaining": null,
"available": true,
"estimated_delivery": "2027-11",
"shipping": "Only certain countries",
"shipping_type": "multiple_locations",
"starts_at": null,
"ends_at": null,
"items": ["Stormlight: War for Roshar"]
}stats ... --history funding.jsonl -f csv (a second run adds the deltas):
id,state,backers_count,pledged,comments_count,url,fetched_at,backers_delta,pledged_delta,comments_delta,previous_at,hours_since
1878275683,live,10194,2521276,1111,https://www.kickstarter.com/projects/brotherwise/war-for-roshar,2026-10-28T00:47:48Z,,,,,
570152316,live,11838,1763869,968,https://www.kickstarter.com/projects/dicethrone/dice-throne-nexus,2026-10-28T00:47:48Z,,,,,
- Money and currencies.
goal,pledged,average_pledgeand reward prices are in the project's owncurrency.goal_usdandpledged_usduse the USD rate Kickstarter fixed for the campaign (usd_rate), so you can compare projects across countries.statsreportspledgedin the project currency. - Paging. The discover search returns 12 projects per page and serves at
most 200 pages (2,400 projects) per query. To collect more, split the query,
for example by subcategory, state or goal range. Each response carries a
ranking seed, which the scraper sends with every later page so the default
magicorder stays consistent while you page. Projects are deduped by ID. - The goal and pledged ranges are Kickstarter's own filter buckets and are in USD.
- Upcoming projects have no launch date or deadline yet (both
null). - Reward limits.
limitandremainingare only set for tiers with a quantity cap.starts_atandends_atare only set for time-boxed tiers. - Campaign story text is not included: it is not part of the project data the page ships.
- Counts from
count()(and thesuccess-rate-by-categoryexample) are the totals Kickstarter's discover search reports. They cover the projects that search lists, so use them to compare categories, not as Kickstarter's official statistics.
| Script | What it does |
|---|---|
examples/live-campaigns-to-csv.js |
The most-funded live staff picks in a category, saved to CSV |
examples/reward-tiers.js |
Which reward tiers backers pick, by estimated share of pledges |
examples/funding-tracker.js |
A cron-friendly watchlist tracker built on stats and trackStats |
examples/success-rate-by-category.js |
Successful vs failed project counts per category |
node examples/live-campaigns-to-csv.js Technology 2
node examples/reward-tiers.js brotherwise/war-for-rosharkickstarter-scraper/
├── bin/cli.js # CLI entry point (argument parsing, output formats)
├── src/
│ ├── index.js # Public exports
│ ├── scraper.js # KickstarterScraper: fetching, retries, paging, dedupe
│ ├── parse.js # Discover JSON, project pages, stats, locations -> records
│ ├── urls.js # URL builders and the search filter vocabulary
│ ├── categories.js # Category tree and name/slug/ID resolution
│ ├── history.js # Funding tracker snapshots and deltas
│ └── util.js # Numbers, dates, entities, CSV, concurrency pool
├── examples/ # Runnable scripts
├── test/ # Offline tests with a mocked client (no API calls)
├── .github/workflows/ci.yml
├── .env.example
└── package.json
npm install
npm test # node:test, fully offline: the ScrapeUnblocker client is mocked
npm run lint # eslintThe tests build small Kickstarter-shaped responses in test/fixtures.js and
cover the parsers, the retry and paging logic, the funding tracker and the CLI
argument parser, so they spend no API credit.
searchbuilds akickstarter.com/discover/advanced?...&format=jsonURL from your filters and fetches it withclient.getPageSource(url). Kickstarter answers with a JSON feed of the matching projects.projectfetches the project page and decodes the project object the page embeds (window.current_project), which holds the funding numbers, creator, location, reward tiers and add-ons.statsfetches<project>/stats.json, a small JSON document with the live counters. That makes it a cheap way to poll many campaigns.- Blocks, timeouts and responses without the expected data are retried with exponential backoff. A real 404 (an unknown project, or a page past the last one) is returned as "not found" and never retried.
MIT © 2026 ScrapeUnblocker
This is an unofficial, educational example. "Kickstarter" is a trademark of Kickstarter, PBC. This project is not affiliated with or endorsed by Kickstarter. Scrape responsibly and respect each site's Terms of Service.