Redbubble Scraper - Print-on-Demand Design & Price Tracker
Pricing
from $0.03 / 1,000 product scrapeds
Redbubble Scraper - Print-on-Demand Design & Price Tracker
Redbubble scraper: search queries to one row per design-on-product result with USD price, product type, variant, artist, tags, link and photo, sorted by relevance, trending, newest or best selling. For print-on-demand trend, new-design and price watching per keyword.
Pricing
from $0.03 / 1,000 product scrapeds
Rating
0.0
(0)
Developer
Superslow Sloth
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Security
Limited permissionsShare
Redbubble scraper: print-on-demand design and price tracker
This Redbubble scraper searches Redbubble by keyword and returns one flat row per search result, a design printed on a product: the title, the artist, the product type and variant, the USD price, stock, the design's tags, the product link and the images. Sort by newest, trending, best selling or relevance, run it on a schedule and diff the dataset to get a print-on-demand trend, new-design and price watch: which new cat, retro or nurse designs appeared this week, which tags they use, and what they sell for.
No account, no API key, no login, no browser. One request returns up to 90 results. Nothing is fetched per result: every row comes from the search pages.
Input
| Field | Notes |
|---|---|
searchQueries | One or more search queries, one per line (cat, black cat sticker, retro sunset, 猫). Each query is read separately. A result found by two queries is returned once, under the first. A query with no match returns nothing and costs nothing. |
maxItems | Results to read per query (default 100, up to 900). Redbubble sends up to 90 per page and serves only the first ten pages of any query, so about 900 is all one query can give, whatever the match count. |
sortOrder | relevant (default), trending, recent (newest designs first) or top selling. |
proxyConfiguration | Apify residential proxy by default. Redbubble refused datacenter addresses when this actor was built. |
Example input:
{"searchQueries": ["cat", "black cat sticker"],"maxItems": 300,"sortOrder": "recent"}
Output
Prices are numbers; currency is USD (every row measured, from exit addresses
in Japan, Serbia and Brazil).
| Field | Notes |
|---|---|
query, sort, position | The query that first found the result, the sort order asked for, and the result's place in the pages read for that query (1 is first, counted over every entry of the pages walked, before duplicates are dropped). The site shuffles part of its order between requests, so this is the position in this run, not a stable rank. |
product_id | Redbubble's inventory id, for example 110162644_bluey-gromit_TBCTK: the design id, a product type code and a blank id. Unique per row. |
work_id | The design's id. It grows with upload time, so a larger number is a newer design; the same work_id repeats when one design is listed on several products. |
title | The design title, whitespace collapsed. |
artist_username, artist_name | The artist's shop name as it appears in links, and the display name. artist_name is null if the page sends none. |
product_type | The product, as the site names it: Sticker, Classic T-Shirt, Poster, Magnet. |
variant | The default variant the price is for, as the site labels it: Small (2.9 x 2.9 in) for a sticker, Black, Front, M for a shirt. Null if the page sends no option labels. |
url | The product page link. |
image_url, artwork_url | The product photo the card shows, and the bare artwork image. Null if the page lists none. |
currency, price | The price of the default variant, as the page shows it. |
discount_percent, discount_amount | The page's discount fields. Null when the site sends 0 (no markdown), never 0. See the note below. |
in_stock | True when the page says in-stock, false for any other status (out-of-stock was seen). Null if the page sends no status. |
tags | The design's tags as the artist set them, usually 10 to 15. Empty list when there are none (63 of 3,297 rows measured). |
mature_content | The page's mature-content flag for the design. |
query_total | How many results Redbubble said the query matches. It drifts by a few between requests (1,554,528 and 1,554,539 for cat minutes apart) and says nothing about depth: only ten pages can be read. |
Example row (real values, 2026-10-29):
{"query": "cat","sort": "recent","position": 2,"product_id": "185127287_sticky-runners_EJUG5","work_id": 185127287,"title": "Catostrophes the bumbling cat we love - pink","artist_username": "Asterisk-a","artist_name": "Asterisk-a","product_type": "Sticker","variant": "Small (2.9 x 2.9 in)","url": "https://www.redbubble.com/i/sticker/Catostrophes-the-bumbling-cat-we-love-pink-by-Asterisk-a/185127287/7sgk","image_url": "https://ih1.redbubble.net/image.6270028846.7287/st,small,507x507-pad,600x600,f8f8f8.jpg","artwork_url": "https://ih1.redbubble.net/image.6270028846.7287/bg,f8f8f8-flat,750x,075,f-pad,750x1000,f8f8f8.jpg","currency": "USD","price": 2.78,"discount_percent": null,"discount_amount": null,"in_stock": true,"tags": ["cat", "kitty", "cat lover", "kitten", "catshirt", "cat mom", "cute animals", "pet", "cat owner", "pussycat", "funnytee", "cartoons", "pet humor", "cat dad", "cat christmas"],"mature_content": false,"query_total": 1554539}
Honest nulls
A field the page did not send is null, never 0 or "". tags is an empty
list when there are none.
- No sales, no favourites, no upload date. The search page carries none of
them.
work_idis the only age signal, andsortOrder: recentlists the newest designs first. - Discounts are unverified. The page has
discountfields on every price, but none of the 5,000+ rows measured on 2026-10-29 had a discount, so it is not known whetherpriceis before or after one. Readdiscount_percentas "the site flagged a markdown" and comparepriceover time. - The price is one variant. Stickers and posters show their default size;
shirts show their default colour, print location and size (
variant). It is not the price range of the product.
How it fetches
It reads the result list that redbubble.com's own search page embeds in its page
data (__NEXT_DATA__). Measured 2026-10-29: HTTP 200 HTML (about 1 MB a page)
from a plain connection and from Apify residential addresses; the pick step
measured datacenter addresses 0 of 10 and residential 9 of 10. A refusal (403,
429, 5xx), a 200 that carries no page data, a page ahead of the one asked for,
or a dropped connection is treated as the address being blocked, and the actor
rotates to a fresh one and retries.
Things worth knowing, all measured:
- Ten pages, then nothing new. Every large query reports ten pages. Asking for page 11, 12 or 13 returns HTTP 200 with the page count still at 10 and a full page of results that is not a new page. The actor stops at the last page the site links to and ignores such an answer. A short list ends sooner (a query with 162 matches gave 90 and 80 results on its two pages; a third page was empty).
- Pages hold up to 90 results, although the site says 82. The first page of
recentheld 82, a last page 80. - The order is not stable. The same search asked twice returned overlapping
but different lists (72 of 90 results shared on
relevant, 66 of 82 onrecent), and a result can appear on two pages of one walk. The actor returns and charges a result once per run. - Sorting is checked. A sort name the site does not know is silently answered
as
relevant; the actor reads which sort the page applied and fails the query instead of returning the wrong order. - Loose matching. Multi-word queries match loosely: invented three-word
phrases matched about 16,000 results. A single rare word narrows sharply
(
qwertyuiopmatched 9). - Country and currency follow the exit address, and are not settable by
parameter (
country=andcurrency=are ignored). Prices were USD from every exit measured.
If Redbubble changes its page data, the run fails with a message instead of returning empty rows.