빠른 시작 V5 (beta)
봇 찾기부터 데이터 받기까지, 첫 수집을 5분 안에 끝냅니다.
v5 는 화면과 같은 말(봇 · 설정 · 주기 · 데이터셋)로 자원을 나눈 API 입니다. 한 봇에 주기를 여러 개 둘 수 있고, 데이터셋에서 그 수집이 수동인지 어느 주기인지, 어떤 조건으로 돌았는지까지 읽을 수 있습니다. 아래 명령은 YOUR_API_KEY만 바꾸면 그대로 동작합니다.
v4 를 쓰고 계신가요? v4 → v5 옮기기 안내를 먼저 보세요. v4 는 그대로 계속 동작합니다.
기계가 읽는 명세는 OpenAPI(JSON)로 받을 수 있습니다.
가입하기 전에 경로를 직접 눌러 보고 싶다면 이 OpenAPI 주소를 Postman·Insomnia 같은 API 도구에서 불러오세요. 모든 경로가 채워져, 가입 뒤 키만 넣으면 바로 호출해 볼 수 있습니다.
-
API 키 복사하기
무료로 가입하고 API 키 받기내 정보 → API 키에서 키를 복사합니다. v4 와 같은 키를 씁니다. 모든 요청의
Authorization헤더에Bearer YOUR_API_KEY형식으로 넣습니다.키는 비밀번호와 같습니다. 코드 저장소·화면 공유에 노출하지 마세요.
가입하면 내 정보 → API 키에서 키를 바로 볼 수 있습니다. 이미 계정이 있으면 로그인하세요.
-
연결 확인하기
GETGET /v5/api/health는 키 없이 부를 수 있는 상태 확인입니다.GET /v5/api/me는 키가 가리키는 계정을 돌려줍니다.요청 예시curl 'https://www.hashscraper.com/v5/api/health'응답 예시 200{ "result": "success", "version": "v5", "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21", "elapsed_sec": 0.0123, "data": { "status": "ok", "time": "2026-10-04T09:00:00+09:00" } }요청 예시curl 'https://www.hashscraper.com/v5/api/me' \ -H 'Authorization: Bearer YOUR_API_KEY'응답 예시 200{ "result": "success", "version": "v5", "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21", "elapsed_sec": 0.0123, "data": { "email": "dev@example.com", "name": "Sample User" } }"result": "success"와 내 이메일이 보이면 준비가 끝났습니다.401이면 키를 다시 복사하세요. -
수집할 봇 고르기
GET내 봇 목록을 받아 수집할 봇의
id를 고릅니다. 봇 상세 화면의 더보기 → 봇 ID 복사하기로도 복사할 수 있습니다.요청 예시curl 'https://www.hashscraper.com/v5/api/bots' \ -H 'Authorization: Bearer YOUR_API_KEY'응답 예시 200{ "result": "success", "version": "v5", "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21", "elapsed_sec": 0.0123, "count": 1, "next_cursor": null, "data": [ { "id": "8f3a7c1e9b5d24f6", "name": "Sample shopping bot", "description": "Collects product lists by keyword.", "schedule_group": null, "union": false, "created_at": "2026-08-12T10:21:05+09:00", "updated_at": "2026-10-01T18:02:40+09:00", "worker_source": { "name": "Shopping list", "version": 12, "updated_at": "2026-09-20T11:00:00+09:00", "price": 5 }, "credit_per_item": 5, "plans_count": 2, "active_plans": [ { "id": "512", "name": "주기 2", "label": "매주 월요일 09:00 (KST)" } ], "period_summary": "주기 2 · 매주 월요일 09:00 (KST)", "next_run_at": "2026-10-05T09:00:00+09:00", "latest_dataset": { "id": 239758028, "status": "done", "data_count": 1280, "trigger": "period", "created_at": "2026-09-28T09:00:03+09:00" } } ] }data[].id가 봇 ID입니다. 다음 단계의 경로에 넣습니다. -
수집 방법 확인하기
GET고른 봇이 어떤 입력(키워드·정렬 등)을 받는지 확인합니다.
inputs의key(또는alias)가 수집 요청 때inputs에 넣을 이름이고,options가 있는 칸은 그 목록의value중에서 고릅니다.요청 예시curl 'https://www.hashscraper.com/v5/api/bots/8f3a7c1e9b5d24f6/inputs' \ -H 'Authorization: Bearer YOUR_API_KEY'응답 예시 200{ "result": "success", "version": "v5", "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21", "elapsed_sec": 0.0123, "data": { "bot_id": "8f3a7c1e9b5d24f6", "excel_supported": true, "inputs": [ { "key": "param1", "name": "Keyword", "name_en": "Keyword", "alias": "keyword", "type": "text", "required": true, "options": [], "excel_supported": true } ] } }봇이 쓰는 칸마다
key·name·options가 보입니다. -
수집 요청하기
POST고른 봇에 수집을 요청합니다. 수집 시작은 재시도 중복 방지 키(
Idempotency-Key헤더)가 필수입니다. 요청 한 번마다 새 키를 만들어 넣으세요(위 예시의$(uuidgen)). 연결이 끊겨 다시 보낼 때만 같은 키를 씁니다. 자세한 규칙은 재시도 중복 방지 키.save_to_settings의 기본값은true입니다. 보낸inputs가 봇 설정에 저장되고 그 값으로 수집합니다. 이번 한 번만 쓰려면false를 보내세요.요청 예시curl -X POST 'https://www.hashscraper.com/v5/api/bots/8f3a7c1e9b5d24f6/collections' \ -H 'Authorization: Bearer YOUR_API_KEY' \ -H "Idempotency-Key: $(uuidgen)" \ -H 'Content-Type: application/json' \ -d '{ "inputs": { "param1": "sneakers" } }'응답 예시 200{ "result": "success", "version": "v5", "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21", "elapsed_sec": 0.0123, "data": { "id": 239758028, "bot": { "id": "8f3a7c1e9b5d24f6", "name": "Sample shopping bot" }, "status": "running", "data_count": 0, "union": false, "trigger": "api", "credits_used": 0, "created_at": "2026-10-04T09:00:02+09:00", "updated_at": "2026-10-04T09:00:02+09:00", "plan": null, "inputs": { "param1": { "name": "Keyword", "value": "sneakers" } }, "started_at": "2026-10-04T09:00:02+09:00", "elapsed_sec": 3, "saved_to_settings": true, "plans_affected": [] } }data.id가 이번 수집(데이터셋)의 번호입니다. 크레딧은 수집이 데이터를 저장할 때 한 줄마다 쓰입니다(크레딧·요청 한도). -
완료될 때까지 확인하기
GET수집은 백그라운드에서 진행됩니다. 10~30초 간격으로 상태를 조회하세요. 사이트와 수집량에 따라 수십 초에서 수십 분이 걸립니다.
요청 예시curl 'https://www.hashscraper.com/v5/api/datasets/239758028' \ -H 'Authorization: Bearer YOUR_API_KEY'응답 예시 200{ "result": "success", "version": "v5", "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21", "elapsed_sec": 0.0123, "data": { "id": 239758028, "bot": { "id": "8f3a7c1e9b5d24f6", "name": "Sample shopping bot" }, "status": "done", "data_count": 1280, "union": false, "trigger": "api", "credits_used": 6400, "created_at": "2026-10-04T09:00:02+09:00", "updated_at": "2026-10-04T09:00:02+09:00", "plan": null, "inputs": { "param1": { "name": "Keyword", "value": "sneakers" } }, "started_at": "2026-10-04T09:00:02+09:00", "elapsed_sec": 94 } }status가done이면 완료입니다.waiting·running·retrying은 진행 중,failed·canceled는 끝났지만 데이터가 모두 모이지 않은 상태,attention은 확인이 필요한 상태(끝났지만 알림이 붙었거나 멈춘 수집)입니다. -
데이터 받기
GET완료된 데이터셋의 데이터를 받습니다. 한 번에
limit건씩 오며, 응답의next_cursor를 다음 요청의cursor로 넘겨 이어 받습니다.요청 예시curl 'https://www.hashscraper.com/v5/api/datasets/239758028/results?limit=1000' \ -H 'Authorization: Bearer YOUR_API_KEY'응답 예시 200{ "result": "success", "version": "v5", "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21", "elapsed_sec": 0.0123, "count": 1, "next_cursor": null, "data": [ { "id": 91000001, "created_at": "2026-10-04T09:00:40+09:00", "updated_at": "2026-10-04T09:00:40+09:00", "title": "Sneakers A", "price": "59000" } ] }next_cursor가null이면 마지막 페이지입니다.
공통 규칙
- 주소 — 모든 경로는
https://www.hashscraper.com/v5/api아래에 있습니다. - 인증 —
Authorization: Bearer <API 키>.health만 키 없이 부를 수 있습니다. - 시각 — ISO 8601, 한국 시간대(
+09:00)입니다. - 크레딧 — 정수입니다.
- 주기 id — 어디서나 글자입니다(
"512"). 숫자로 비교하지 마세요. - 요청 번호 — 요청에
X-Request-ID: req_...를 보내면 그대로 돌려주고, 없으면 서버가 만듭니다. 문의할 때 알려 주세요.
| 응답 칸 | 설명 |
|---|---|
result | success 또는 error. 여러 항목을 한 번에 처리하는 묶음 수집은 partial_success·failure도 있습니다. |
version | 항상 v5. |
request_id | 요청 번호. |
elapsed_sec | 응답을 만드는 데 걸린 시간(초). |
data | 결과. 목록이면 배열, 하나면 객체. 칸은 늘 같은 모양이고, 값이 없으면 빠지지 않고 null·빈 배열로 옵니다. |
count·next_cursor | 목록 응답에만. 이번에 받은 개수와 다음 쪽 표지(없으면 null). |
목록 이어 받기
목록은 limit(기본 100, 최대 1000)건씩 옵니다. 응답의 next_cursor를 다음 요청의 cursor로 그대로 넘기세요. null이면 끝입니다. 이어 받는 도중 sorting 같은 조건을 바꾸지 마세요.
처음부터 끝까지 한 번에 (Python · Node.js)
위 5–7단계(수집 요청 → 완료 확인 → 데이터 받기)를 이어 붙인 코드입니다. YOUR_API_KEY·봇 ID 와 함께 inputs도 4단계(GET /bots/{bot_id}/inputs)에서 확인한 그 봇의 입력 칸으로 바꾸세요(예시의 param1: "sneakers"는 키워드 칸이 하나인 봇 기준입니다). 이 예시는 save_to_settings: false로 보내 봇 설정을 바꾸지 않습니다. 이번만 다른 조건으로 돌릴 수 없는 봇은 422 PLAN_CONDITION_BLOCKED가 오니, 그때는 이 칸을 빼고 보내세요.
크레딧이 언제 얼마나 쓰이는지, 1분에 몇 번까지 부를 수 있는지는 크레딧·요청 한도를 보세요.
import time
import uuid
import requests
BASE = "https://www.hashscraper.com/v5/api"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
BOT_ID = "8f3a7c1e9b5d24f6"
# 1. start a collection (a new Idempotency-Key for every new request)
res = requests.post(
f"{BASE}/bots/{BOT_ID}/collections",
headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
json={"inputs": {"param1": "sneakers"}, "save_to_settings": False}, # this run only
timeout=30,
)
res.raise_for_status()
dataset_id = res.json()["data"]["id"]
# 2. wait until it ends (check every 20 seconds)
while True:
dataset = requests.get(f"{BASE}/datasets/{dataset_id}", headers=HEADERS, timeout=30).json()["data"]
if dataset["status"] in ("done", "attention", "failed", "canceled"): # attention = ended with a notice, or stalled
break
time.sleep(20)
print(dataset["status"], dataset["data_count"], "rows", dataset["credits_used"], "credits")
# 3. download every row (until next_cursor is null)
rows, cursor = [], None
while True:
params = {"limit": 1000, **({"cursor": cursor} if cursor else {})}
page = requests.get(f"{BASE}/datasets/{dataset_id}/results", headers=HEADERS, params=params, timeout=60).json()
rows.extend(page["data"])
cursor = page["next_cursor"]
if cursor is None:
break
print(len(rows), "rows downloaded")
// Node.js 18+ (built-in fetch)
const { randomUUID } = require("node:crypto");
const BASE = "https://www.hashscraper.com/v5/api";
const HEADERS = { Authorization: "Bearer YOUR_API_KEY" };
const BOT_ID = "8f3a7c1e9b5d24f6";
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function call(method, path, { body, query } = {}) {
const url = new URL(BASE + path);
for (const [k, v] of Object.entries(query ?? {})) if (v != null) url.searchParams.set(k, v);
const headers = { ...HEADERS };
if (method !== "GET") headers["Idempotency-Key"] = randomUUID(); // a new key for every new request
if (body) headers["Content-Type"] = "application/json";
const res = await fetch(url, { method, headers, body: body ? JSON.stringify(body) : undefined });
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
return res.json();
}
async function main() {
// 1. start a collection
const started = await call("POST", `/bots/${BOT_ID}/collections`, {
body: { inputs: { param1: "sneakers" }, save_to_settings: false }, // this run only
});
const datasetId = started.data.id;
// 2. wait until it ends (check every 20 seconds)
let dataset;
for (;;) {
dataset = (await call("GET", `/datasets/${datasetId}`)).data;
if (["done", "attention", "failed", "canceled"].includes(dataset.status)) break; // attention = ended with a notice, or stalled
await sleep(20000);
}
console.log(dataset.status, dataset.data_count, "rows", dataset.credits_used, "credits");
// 3. download every row (until next_cursor is null)
const rows = [];
let cursor = null;
do {
const page = await call("GET", `/datasets/${datasetId}/results`, { query: { limit: 1000, cursor } });
rows.push(...page.data);
cursor = page.next_cursor;
} while (cursor !== null);
console.log(rows.length, "rows downloaded");
}
main().catch((err) => {
console.error(err.message);
process.exitCode = 1;
});