Rakuma Scraper – Rakuten Flea Market Japan (楽天ラクマ)
Pricing
from $2.00 / 1,000 results
Rakuma Scraper – Rakuten Flea Market Japan (楽天ラクマ)
Scrape Rakuma (fril.jp, 楽天ラクマ) — Rakuten's flea-market app, Japan's #2 C2C marketplace: fashion, brand bags, sneakers, hobby. Search by keyword, brand, category, price, condition, sold-out; get normalized size, condition rank, seller and images. JP Data Works series.
Pricing
from $2.00 / 1,000 results
Rating
0.0
(0)
Developer
JP Data Works
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Scrape Rakuma (楽天ラクマ) — Rakuten's flea-market app and Japan's second-largest C2C marketplace after Mercari (tens of millions of listings: fashion, brand bags and shoes, sneakers, cosmetics, hobby, kids) — by keyword, brand and category, with price, condition, sold-out and exclude-word filters, and get clean JSON / CSV with normalized size, condition rank (6–1), category path, seller and images. Optionally open each item page for condition, size, shipping, seller reviews, likes, description and the full gallery. Part of the JP Data Works series of Japanese marketplace scrapers (Mercari, Yahoo! Fleamarket, KOMEHYO, Trefac, Vector Park …) that share one output shape so results can be merged.
Keywords: Rakuma scraper · ラクマ スクレイピング · fril.jp · Rakuten flea market data · Japanese secondhand prices · sold listings price research · KAPITAL, visvim, Comme des Garçons, Supreme, Nike SB used · resale sourcing (eBay, Grailed, Depop, StockX) · price monitoring.
What you get
One row per listing:
itemId,itemHash,url,title,brand,brandIdpriceJpy,status(on_sale/sold),sizeRaw/sizeNorm/size(W32,L,JP3,26.5cm,FREE)categoryId,categoryPath(メンズ > ジャケット/アウター > Gジャン/デニムジャケット — from the listing card's leaf category),categoryIds,gendersellerId,imageUrl/imageUrls,fetchedAt,keyword,search
With Enrich with item pages each item additionally has conditionRank 6 (新品、未使用) … 1 (全体的に状態が悪い) and conditionLabel, sizeRaw from the item page, shippingPayer (seller 送料込 / buyer 着払い), shippingMethod, shippingDuration, shippingFromArea, anonymousShipping, sellerName, shopName, shopHash, sellerReviews ({ good, neutral, bad }), likes, comments, description and the full-size gallery.
Example item (enriched)
{"source": "rakuma","itemId": "862187021","itemHash": "d61f0b0fcd51aaf40a346d015f3af984","url": "https://item.fril.jp/d61f0b0fcd51aaf40a346d015f3af984","title": "KAPITAL","brand": "KAPITAL","brandId": "1785","priceJpy": 50000,"status": "on_sale","sizeRaw": "L","sizeNorm": { "kind": "alpha", "value": "L" },"size": "L","conditionRank": 3,"conditionLabel": "やや傷や汚れあり","categoryId": 542,"categoryPath": "メンズ > ジャケット/アウター > Gジャン/デニムジャケット","categoryIds": [10005, 539, 542],"gender": "mens","sellerId": "17052770","sellerName": "rkm0510","shopHash": "ddb32042513b176103c3d77a30b5beb2","shopName": "rkm0510's shop","sellerReviews": { "good": 32, "neutral": 0, "bad": 0 },"shippingPayer": "seller","shippingMethod": "かんたんラクマパック(日本郵便)","shippingDuration": "支払い後、4~7日で発送","shippingFromArea": "静岡県","anonymousShipping": true,"likes": 1,"comments": 0,"description": "ご覧いただきありがとうございます。\n\nストライプ柄フードとダブルブレストが特徴的なインディゴデニム素材のジャケットです。…","imageUrl": "https://img.fril.jp/img/862187021/l/2990237096.jpg","imageUrls": ["…/l/2990237096.jpg", "…/l/2990237088.jpg", "…/l/2990237184.jpg"],"fetchedAt": "2026-11-02T03:08:40.000Z","detailFetchedAt": "2026-11-02T03:08:47.574Z","keyword": "brand:KAPITAL#1785 メンズ>ジャケット/アウター ¥–60000","search": { "label": "brand:KAPITAL#1785 メンズ>ジャケット/アウター ¥–60000", "mode": "brand_category", "brandId": "1785", "categoryId": 539, "categoryNames": ["メンズ", "ジャケット/アウター"], "priceMaxJpy": 60000, "status": "on_sale", "clientSideFilters": ["price ¥–60000", "status=on_sale"], "url": "https://fril.jp/brand/1785/category/539" }}
Without enrichment the detail fields are null and imageUrls holds the listing image, so the dataset always has the same columns.
Output modes — listings or a market summary
outputMode chooses what the dataset contains:
items(default) — one row per listing, as above.summary— one market-summary row per search instead of the listings. The Actor still walks the search pages (up tomaxItemsPerSearchlistings, withenrichDetailif set), but stores only the aggregate — so a run that answers "what does X go for on Rakuma?" costs onesummaryevent per search rather than hundreds of result events.both— the listings plus the summary row.
A summary row (recordType: "summary") has the same shape in every JP Data Works Actor, so you can put several sites side by side:
{"recordType": "summary","source": "rakuma","search": { "label": "…", "url": "…", "…": "the resolved search parameters" },"fetchedAt": "2026-11-02T03:00:00.000Z","sampleSize": 180, "totalOnSite": 1243, "scanned": 190, "filteredOut": 10, "withDetail": 0,"status": { "on_sale": 180, "sold": 0, "unknown": 0 },"price": { "count": 180, "min": 3300, "p25": 9800, "median": 16500, "mean": 19840, "p75": 25300, "max": 128000, "stddev": 15210 },"priceOnSale": { "…": "same statistics for on-sale listings" }, "priceSold": { "…": "and for sold ones (sites that list them)" },"priceHistogram": { "bucketJpy": 10000, "buckets": [ { "fromJpy": 0, "toJpy": 10000, "count": 46 }, "…" ] },"conditionRank": { "6": 12, "5": 40, "4": 71, "3": 30, "unknown": 27 }, "conditionLabels": { "…": "the site's own labels" },"sizes": { "M": 48, "L": 41, "W32": 12, "…": 0 }, "sizeKinds": { "alpha": 120, "waist": 30, "numeric": 20, "unknown": 10 },"brands": { "KAPITAL": 180 }, "categories": { "メンズ > ジャケット/アウター": 95, "…": 0 }, "gender": { "mens": 170, "unknown": 10 },"listed": { "last24h": 9, "last7d": 41, "last30d": 120 }, "sold": null,"cheapest": [ { "itemId": "…", "title": "…", "url": "…", "priceJpy": 3300, "conditionRank": 4, "size": "M", "status": "on_sale" }, "…" ],"cheapestGoodCondition": [ "… cheapest with condition rank ≥ 4 …" ],"newest": [ "… most recently listed (sites that expose listing times) …" ]}
Rakuma keeps sold listings in its catalogue, so with status: "all" the summary separates priceOnSale from priceSold — a quick asking-price vs sold-price comparison. The site exposes no listing time, so listed / sold are null.
Input
Two ways to describe what to search, which can be combined in one run:
keywords— simple: one search per keyword (KAPITAL,リーバイス 501,Porter タンカー…).searches— structured: objects with any ofkeyword,brand/brandId,categoryPath/categoryId,priceMinJpy,priceMaxJpy,conditionMin,status,excludeWords,sellerId.
Top-level status, priceMinJpy, priceMaxJpy, conditionMin, excludeWords are defaults for every keyword and search; a value inside a search wins.
| Field | Type | Default | Notes |
|---|---|---|---|
keywords | string[] | — | One search per keyword. Optional when searches is given. |
outputMode | items | summary | both | items | Listings, one market-summary row per search, or both (see "Output modes"). |
searches | object[] | — | Structured searches (table below). Each needs a keyword, brand or category. |
status | on_sale | sold | all | on_sale | sold = sold-out listings only, with their last price. |
priceMinJpy / priceMaxJpy | integer | none | Client-side (the site's price filter is robots-disallowed). |
conditionMin | 2–6 | none | Needs item pages → turns on enrichDetail. |
excludeWords | string[] | [] | Client-side title filter. |
maxItemsPerSearch | integer | 100 | Per keyword / search. 40 cards per page, 100 pages max. |
maxTotalItems | integer | none | Hard cap per run. |
dedupeAcrossSearches | boolean | true | |
enrichDetail | boolean | false | One extra request + one detail-page event per item. |
maxDetailPages | integer | 100 | Cap on item-page requests per run. |
requestDelayMs | integer | 2000 | Minimum pause between requests. Please keep ≥ 2000. |
proxyConfiguration | object | none | Optional. Not needed under normal use. |
outputFields | string[] | all | Keep only these fields (itemId, url always kept). |
Fields of one searches entry (all optional):
| Field | Example | How it is applied |
|---|---|---|
keyword | "KAPITAL デニム" | Site keyword search (/s?query=), relevance order. |
brand | "KAPITAL", "COMME des GARCONS" | Searched once as a keyword; the brand id is read from the result cards (one extra request per distinct brand). Unknown names are searched as a keyword and filtered by brand name client-side. |
brandId | 1785 | The site's brand id (fril.jp/brand/<id>). 1785 = KAPITAL. |
categoryPath | "mens", "ladies", "mens > jackets", "mens > jackets > denim jacket", "メンズ > パンツ > デニム/ジーンズ", "ladies > バッグ" | Top category (mens, ladies, kids, cosmetics, hobby, or the Japanese name) optionally followed by > and sub-category names as shown on the site (Japanese, or English for the common ones: tops, jackets, pants, shoes, bags, denim, sneakers, boots, knit, coat, dress, skirt …). The full tree (1,686 categories) is bundled. A name that exists under several parents (e.g. ジャケット/アウター) needs its parent. Unknown paths are used as an extra keyword. |
categoryId | 542 | The site's category id (fril.jp/category/<id>). |
priceMinJpy / priceMaxJpy | 5000 / 30000 | Client-side from the card price. |
conditionMin | 4 | Client-side after the item page: 6 新品、未使用, 5 未使用に近い, 4 目立った傷や汚れなし, 3 やや傷や汚れあり, 2 傷や汚れあり. |
status | "sold" | on_sale (default), sold, all — from the card's SOLD OUT ribbon. |
excludeWords | ["ダメージ"] | Client-side: drop items whose title contains any of these. |
sellerId | "17052770" | Client-side: keep only this seller's listings. |
How the search is routed (robots.txt forbids combining a keyword with brand_id= / category_id=, so the Actor uses the page types it allows):
| Input | Page crawled | Client-side |
|---|---|---|
keyword only | /s?query=<kw>&page=N | — |
keyword + brand / category | /s?query=<kw>&page=N | cards filtered by the brand link / leaf category (and all its sub-categories) |
brand only | /brand/<id>/page/N | — |
brand + category | /brand/<id>/category/<cid>/page/N | — |
category only | /category/<cid>/page/N | — |
Examples
Sold KAPITAL jackets — what they actually went for (price research):
{"searches": [{ "brand": "KAPITAL", "categoryPath": "mens > jackets", "status": "sold" }],"maxItemsPerSearch": 200}
Men's denim under ¥20,000 in good condition, with seller and shipping details:
{"searches": [{ "categoryPath": "mens > pants > denim", "priceMaxJpy": 20000, "conditionMin": 4 }],"maxItemsPerSearch": 100,"enrichDetail": true,"maxDetailPages": 100}
Keyword within one brand (keyword search filtered by brand client-side):
{ "searches": [{ "keyword": "センチュリーデニム", "brand": "KAPITAL", "status": "all" }], "maxItemsPerSearch": 100 }
Requests are strictly sequential: 100 listings ≈ 3 search pages ≈ 6 seconds; with enrichDetail ≈ 103 requests ≈ 3.5 minutes at the default delay (+1 request when brand names need to be resolved).
Search URL parameters (how the filters map to fril.jp)
Discovered from the site's search form, pager and robots.txt (2026-11-02):
https://fril.jp/s?query=KAPITAL&page=2 https://fril.jp/brand/1785/category/539/page/2 https://fril.jp/category/542/page/2
| Actor field | Site URL | Notes |
|---|---|---|
keyword | /s?query= | relevance order (the sort= parameter is robots-disallowed, so no newest-first) |
brandId | /brand/<id> | brand page; /brand/<id>/category/<cid> for one category |
categoryId | /category/<id> | 3-level tree: 10001 レディース, 10005 メンズ, 10003 キッズ/ベビー/マタニティ, 10004 コスメ/美容, 10007 エンタメ/ホビー, 10013 楽器, 10008 チケット … |
| (pagination) | ?page=N / /page/N | 40 cards per page, up to 100 pages |
| price, condition, status, size | — | the site's min=, max=, status=, size_id=, sort=, brand_id=, category_id= query parameters are all robots-disallowed; the Actor never sends them and filters client-side instead |
Pricing (pay per event)
This Actor uses Apify's pay-per-event model. You only pay for what it produces:
| Event | Charged when | Price |
|---|---|---|
Result (apify-default-dataset-item, charged automatically by Apify) | one listing is saved to the dataset | $0.002 |
Detail page (detail-page) | that listing was enriched from its item page | $0.005 (in addition to the result) |
Market summary (summary) | one summary row is saved (outputMode summary / both) | $0.03 per search |
Actor start (apify-actor-start) | each run starts | $0.00005 |
Example: 100 listings with detail ≈ 100 × $0.002 + 100 × $0.005 = $0.70. Without detail: $0.20.
A summary-only run over 3 searches ≈ 3 × $0.03 = $0.09, whatever the number of listings sampled.
Set Max total charge on the run to cap spending — the Actor stops cleanly when the limit is reached and you keep everything collected so far.
FAQ
What is Rakuma? Rakuma (楽天ラクマ, formerly Fril) is Rakuten's consumer-to-consumer flea-market app, Japan's second-largest after Mercari, with a strong fashion and brand-goods catalogue and lower seller fees — prices for the same item are often a little below Mercari. Listings are public at fril.jp; sold items stay visible with a SOLD OUT ribbon.
Why is there no "newest first" sort?
fril.jp's robots.txt disallows every URL carrying sort= (and the price / condition / size / brand / category query parameters). The Actor only requests the page types the site allows, so results come in the site's default order and all other filters run client-side on the listing cards. For new-arrival monitoring, schedule the Actor and diff itemId against the previous run.
Can I get sold items?
Yes — status: "sold" returns sold-out listings with their last price (listings stay in the catalogue after sale), which makes Rakuma a good source for "what did it actually sell for". Sold item pages no longer show the condition and size table, so conditionRank is usually null for them even with enrichment.
Do I need a proxy?
No. The site serves the listing and item pages to Apify's datacenter IPs at the default 2-second delay. proxyConfiguration is there if you need it.
How are sizes and conditions normalized?
sizeRaw keeps the site text (item page) or the size found in the title; sizeNorm interprets it (waist inches for W32, alpha for S/M/L/LL→XL, numeric for JP sizes such as 3, cm for shoes, free). conditionRank uses 6 = best … 1 = worst — the same scale as our Mercari, Yahoo! Fleamarket, KOMEHYO, Trefac and Vector Park scrapers, so results from several Actors can be merged; conditionLabel keeps Rakuma's own wording.
Is this legal? The Actor collects public listing data only — no login, no purchases, no personal data beyond the public seller name — obeys robots.txt (including the disallowed query parameters) and throttles requests. How you use the data is your responsibility; respect the site's terms of use, keep runs small and scheduled, and do not republish its photos or texts as your own.
How do I call it from code or from an AI agent? Any Apify client works. With the JavaScript client:
import { ApifyClient } from "apify-client";const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor("tokyo-select-jp/rakuma-search-scraper").call({searches: [{ brand: "KAPITAL", categoryPath: "mens > jackets", status: "sold" }],maxItemsPerSearch: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
or with plain HTTP (run-sync-get-dataset-items returns the results directly):
POST https://api.apify.com/v2/acts/tokyo-select-jp~rakuma-search-scraper/run-sync-get-dataset-items?token=YOUR_TOKENContent-Type: application/json{ "keywords": ["visvim"], "maxItemsPerSearch": 50 }