Rakuma API & Scraper
Rakuma (楽天ラクマ, formerly Fril) is Rakuten's consumer-to-consumer flea market and one of Japan's two big secondhand marketplaces alongside Mercari.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
This API reads its public listing pages: a keyword, category or brand search that returns 40 listings a page with price in yen, the sold/on-sale state, brand, category id, seller id and seller kind, the Rakuten point rebate and a photo URL; a full item record with the seller's own description, condition grade, size, every photo, shipping terms and dispatch region, like and comment counts, and the seller's shop; a seller endpoint with the shop's average transaction rating, how many ratings are behind it, how many items it has listed and a page of its current stock; and a category endpoint that turns Rakuma's numeric category ids into names. Both sides of the market are available — on one keyword measured on 2026-10-02 the catalogue split 253,340 listings still for sale and 1,017,357 already sold, and a sold listing is returned with its price intact rather than as a 404, because the sold price is usually the number people came for.
What a Rakuma search row and item record contain
Every number below was measured on live fril.jp pages on 2026-10-02, including the ones that work against us. Fields the source does not publish are listed as not published rather than filled with nulls.
| Field | Type | Notes (measured) |
|---|---|---|
| item_id | string | 32-character hex id — the only id that resolves to a listing page |
| item_number | string | Rakuma's second, numeric id for the same listing. It is NOT an address (requesting it returns 404); it is the key inside the photo URLs. Both are returned so you never resolve the wrong one |
| price_jpy | integer | Price in yen. Yen has no minor unit; verified against three separate values the page itself prints, 160/160 search rows and 12/12 item pages agreed |
| price_display | string | The source's own rendered string, e.g. "¥2,080", so you can check our integer against it |
| is_sold | boolean | Read from the page's own sold ribbon. Rakuma's structured data claims "InStock" on sold listings — 8 of 8 sold items measured — so that value is not republished |
| condition | enum | new · like_new · no_noticeable_flaws · slight_flaws · visible_flaws · poor. Verified against each item page's own condition text, 18/18 agreed |
| size | string | Item page only; 12/12 records carried one, including the seller's own answer "none" |
| brand_id / brand_name | string | Sparse and honestly so: filled on 26/40 womenswear rows but only 3/40 electronics rows — most private sellers do not pick a brand |
| category_id | string | Numeric Rakuma category. Names come from the categories endpoint or an item record's category_path; the search surface publishes the id only, so we publish the id only |
| seller_user_id / seller_type | string | Every row, 320/320. seller_type is business or individual |
| point_rebate_jpy / point_rebate_rate_pct | number | The Rakuten point rebate the listing carries, every row. A rebate of 0 stays 0 |
| images | string[] | Item record only: 6 to 21 photos, median 13 across 12 records |
| seller.rating / rating_count | number | Shop endpoint: average out of 5 and the number of transaction ratings behind it. Cross-checked — one shop's three per-outcome counters (1290 good, 29 neutral, 7 bad) summed exactly to its published count of 1,326 |
| likes_count / comments_count | integer | Item record only |
| listed_at | null | Not published. Nothing on the card, the item page or its structured data carries a listing date, so we return null instead of inventing one — you can still sort newest-first |
| stock / quantity | null | Not published and not invented. Rakuma is C2C: every listing is a single copy |
Paging is honest about its ceiling: 40 rows a page, page 100 is the last one that answers (101 is a 404), so at most 4,000 rows are reachable for one query however large the result total is. Nine sampled pages returned 360 rows with zero duplicates. Narrow with the filters rather than paging deeper. One more caveat worth knowing: Rakuma matches keywords loosely, and for a keyword with no real match it reports an approximate total of 200 and still returns token-level matches — the response flags that with total_results_is_approximate.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/rakuma/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"query": "nike",
"max_results": 20
}
}{
"ok": true,
"meta": {
"api": "rakuma",
"endpoint": "search",
"mode": "live",
"latency_ms": 1891.7,
"record_count": 40,
"bytes": 495551,
"cache_hit": false,
"stop_reason": "complete",
"promoted_rows": 0,
"non_listing_tiles_dropped": 0,
"source_hits_attribute": 40,
"upstream_requests": 1,
"charged_credits": 1,
"version": "1.0.0",
"request_id": "c99a74ba6ef54cf9",
"queue_ms": 1.3
},
"data": {
"total_results": 1270088,
"total_results_is_approximate": false,
"total_results_note": "The source prints a rounded figure on the page (約1,270,000件) and the precise one in its own data attribute; the precise one is returned. A keyword with no real match always reports exactly 200 - treat that as 'approximately nothing', which is what `total_results_is_approximate` marks.",
"source_result_header": "約1,270,000件中 1 - 40件",
"page": 1,
"page_size": 40,
"page_max": 100,
"reachable_rows": 4000,
"returned": 40,
"promoted_rows": 0,
"filters": {
"query": "nike",
"exclude_query": null,
"category_id": null,
"brand_id": null,
"condition": null,
"availability": null,
"shipping_payer": null,
"listing_source": null,
"price_min": null,
"price_max": null,
"sort": "relevance",
"order": "desc",
"page": 1
},
"rows": [
{
"item_id": "364d2a7999a8c318b17ed48d7e4572d1",
"item_number": "852271685",
"url": "https://item.fril.jp/364d2a7999a8c318b17ed48d7e4572d1",
"title": "【値引き交渉OK!】90s NIKE GOLF ナイキゴルフ プルオーバーナイロンジャケット ヴィンテージ 刺繍 黒 ブラック Mサイズ 古着",
"price_jpy": 2080,
"price_display": "¥2,080",
"price_before_discount_jpy": null,
"price_disagrees_with_source": false,
"currency": "JPY",
"is_sold": false,
"image_url": "https://img.fril.jp/img/852271685/m/2945917122.JPG",
"brand_id": "592",
"brand_name": "NIKE",
"category_id": "547",
"seller_user_id": "23309276",
"seller_type": "business",
"point_rebate_jpy": 20,
"point_rebate_rate_pct": 1,
"is_promoted": false,
"source_surface": "search"
},
{
"item_id": "e625c47af57b33f789358726ef1f6239",
"item_number": "852271731",
"url": "https://item.fril.jp/e625c47af57b33f789358726ef1f6239",
"title": "【値引き交渉OK!】NIKE ナイキ ハーフジップフリースプルオーバージャケット/ボアジャケット スウッシュ 水色 ブルー XLサイズ 古着",
"price_jpy": 2080,
"price_display": "¥2,080",
"price_before_discount_jpy": null,
"price_disagrees_with_source": false,
"currency": "JPY",
"is_sold": false,
"image_url": "https://img.fril.jp/img/852271731/m/2945918317.JPG",
"brand_id": "592",
"brand_name": "NIKE",
"category_id": "561",
"seller_user_id": "23309276",
"seller_type": "business",
"point_rebate_jpy": 20,
"point_rebate_rate_pct": 1,
"is_promoted": false,
"source_surface": "search"
},
{
"item_id": "4d32f52d554b79f9798ba24669ff39a4",
"item_number": "852272166",
"url": "https://item.fril.jp/4d32f52d554b79f9798ba24669ff39a4",
"title": "【値引き交渉OK!】NIKE ナイキ トラックジャケット/ジャージ ショッキングピンク Lサイズ 古着",
"price_jpy": 2080,
"price_display": "¥2,080",
"price_before_discount_jpy": null,
"price_disagrees_with_source": false,
"currency": "JPY",
"is_sold": false,
"image_url": "https://img.fril.jp/img/852272166/m/2945920711.JPG",
"brand_id": "592",
"brand_name": "NIKE",
"category_id": "536",
"seller_user_id": "23309276",
"seller_type": "business",
"point_rebate_jpy": 20,
"point_rebate_rate_pct": 1,
"is_promoted": false,
"source_surface": "search"
}
]
}
}What the Rakuma API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search Rakuma listings by keyword, category or brand, with condition, availability, shipping-payer, seller-kind and price filters. 🔴 At least ONE of `query`, `category_id` or `brand_id` is required (the framework cannot express "one of", so it is stated here and in the error message). Returns 40 rows per page with the source's own result total, and both the sold and the on-sale side of the market. | Price-intelligence teams call search to search Rakuma listings by keyword, category or brand, with condition, availability, shipping-…. | query, exclude_query, category_id, brand_id, condition, ... |
| item | One full Rakuma listing: title, the seller's own description, price, condition grade, size, brand, the full category path, every photo, shipping terms and origin region, like and comment counts, Rakuten point rebate, and the seller's shop with its three transaction-review counters. A sold listing is returned with its price and `is_sold: true`, not as NOT_FOUND. | Classifieds aggregators call item to get one full Rakuma listing. | item_id |
| seller | A Rakuma seller's shop: its shop display name AND its user handle (two different strings upstream), the official-shop badge, the average transaction rating out of 5 with the number of ratings behind it, ratings behind it, the total number of items it has listed, and one page of its current stock (36 rows per page on this surface, measured, with 0 overlap between page 1 and page 2). | Resale and arbitrage tools call seller to get a Rakuma seller's shop. | seller_id, page |
| categories | Rakuma's category ids and names. With no parameter it returns the 14 top-level departments (no request upstream). With `category_id` it returns that department's child categories with their Japanese names - 13 for menswear, for example. The ids feed `search`'s `category_id`, which is how you get a live item count for one of them. | Lead-generation teams call categories to get rakuma's category ids and names. | category_id |
Call search from your stack
curl -X POST https://api.reefapi.com/rakuma/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"nike","max_results":20}'import requests
r = requests.post(
"https://api.reefapi.com/rakuma/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "nike",
"max_results": 20
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/rakuma/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"query": "nike",
"max_results": 20
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.rakuma.search with {"query":"nike","max_results":20}.Who uses this API and why
- Resale price research for Japanese fashion: pull the sold side of the market for a brand or model, with condition grade and size, to see what items actually closed at rather than what sellers are asking.
- Cross-marketplace arbitrage between Rakuma and Mercari Japan: the same brand and category on both, with the Rakuten point rebate included so the effective price is comparable.
- Sneaker and streetwear comps: filter by brand id and condition new, sort by newest, and track asking prices and how fast listings disappear into the sold-out side.
- Seller and shop intelligence: resolve a listing to its shop, then read the shop's rating, how many ratings back it, how many items it has listed and its current stock — useful for sourcing from Rakuten-vetted official shops.
- Catalogue and trend monitoring for Japanese secondhand retail: walk the category tree, take live result totals per category, and watch which conditions and price bands the volume sits in.
Questions developers ask before integrating
What is Rakuma and how is it different from Mercari?
Rakuma (楽天ラクマ) is Rakuten's consumer-to-consumer flea-market app, formerly called Fril, and it runs on fril.jp. Like Mercari Japan it is dominated by secondhand fashion, sneakers, bags and cosmetics sold by private individuals, but because it is Rakuten's it carries Rakuten point rebates on listings and has a vetted "official shop" tier of business sellers. This API returns the rebate per listing and tells you which tier a seller is in — on one keyword measured 2026-10-02, 4.1% of listings came from official shops and 95.9% from private sellers.
Can I get sold listings, not just active ones?
Yes, and that is most of the catalogue. Set availability to sold_out. On the keyword measured 2026-10-02 the split was 253,340 on sale and 1,017,357 sold, and the two add up to the unfiltered total of 1,270,699. Sold listings keep their price and come back with is_sold true — they are an answer, not an error.
How many listings can I actually page through for one search?
4,000. Page size is a fixed 40 rows and page 100 is the last page that answers; page 101 returns a 404 upstream, so the API rejects it with a clear message instead. Nine sampled pages gave 360 rows with zero duplicates between them, so the 4,000 are 4,000 distinct listings. If a query reports more results than that, split it with the category, brand, price or condition filters.
Are the condition grades reliable?
They are Rakuma's own six seller-declared grades, and we checked the mapping rather than assuming it: for each grade we filtered on it and then read three of the returned items' own condition text from their item pages — 18 of 18 agreed. The six grades' result counts also add up to the unfiltered total to within 0.005%. Note these are the seller's declaration, not an inspection by Rakuten.
Is the price in yen or in some sub-unit?
Plain yen as an integer: 2080 means ¥2,080. Yen has no minor unit, but we verified it anyway against three different values the page prints for the same listing plus the structured data on the item page. 160 of 160 search rows and 12 of 12 item pages agreed, and we return the source's own rendered string in price_display so you can check ours. If the witnesses ever disagree, the row carries price_disagrees_with_source.
Why is brand often empty?
Because most private sellers do not select one. Measured across four departments: 26/40 rows in womenswear, 15/40 in cosmetics, 17/40 in sport, and as few as 3/40 in electronics. We report it as null rather than guessing a brand from the title. If you need brand-complete data, filter by brand_id — then every row carries it by definition.
Can I search by size?
Not as a filter. Rakuma's own size parameters were probed: the per-size one returns a 404 for every value we tried, and the size-group one does change results but Rakuma publishes no readable list of its values. We do not ship a filter we cannot explain, so size is returned as a field on every item record instead — 12 of 12 records carried one — and you filter on it yourself.
Does the API do Japanese or English keywords?
Both, with Japanese working better because that is what sellers write. Katakana brand names (ナイキ) and Latin ones (NIKE) both resolve, and you can exclude words too — excluding GOLF took one keyword from 1,270,699 results to 1,226,515 in the same run. Titles, descriptions, condition labels and category names come back in Japanese, as the source publishes them.
What is the Rakuma API?
Rakuma API is a ReefAPI endpoint group for japan's rakuten-run c2c resale marketplace — fril.jp listings, items and seller shops It returns live JSON through POST requests under /rakuma/v1.
Is the Rakuma API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Rakuma calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Rakuma login or account?
No login to Rakuma is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Rakuma data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Rakuma API use?
Rakuma actions currently cost 1-3 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Rakuma from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call rakuma actions with the same key, credit pool and JSON envelope used by normal REST requests.