빠른 시작 V5 (beta)

봇 찾기부터 데이터 받기까지, 첫 수집을 5분 안에 끝냅니다.

v5 는 화면과 같은 말(봇 · 설정 · 주기 · 데이터셋)로 자원을 나눈 API 입니다. 한 봇에 주기를 여러 개 둘 수 있고, 데이터셋에서 그 수집이 수동인지 어느 주기인지, 어떤 조건으로 돌았는지까지 읽을 수 있습니다. 아래 명령은 YOUR_API_KEY만 바꾸면 그대로 동작합니다.

v4 를 쓰고 계신가요? v4 → v5 옮기기 안내를 먼저 보세요. v4 는 그대로 계속 동작합니다.

기계가 읽는 명세는 OpenAPI(JSON)로 받을 수 있습니다.

가입하기 전에 경로를 직접 눌러 보고 싶다면 이 OpenAPI 주소를 Postman·Insomnia 같은 API 도구에서 불러오세요. 모든 경로가 채워져, 가입 뒤 키만 넣으면 바로 호출해 볼 수 있습니다.

  1. API 키 복사하기

    내 정보 → API 키에서 키를 복사합니다. v4 와 같은 키를 씁니다. 모든 요청의 Authorization 헤더에 Bearer YOUR_API_KEY 형식으로 넣습니다.

    키는 비밀번호와 같습니다. 코드 저장소·화면 공유에 노출하지 마세요.

    무료로 가입하고 API 키 받기

    가입하면 내 정보 → API 키에서 키를 바로 볼 수 있습니다. 이미 계정이 있으면 로그인하세요.

  2. 연결 확인하기

    GET

    GET /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이면 키를 다시 복사하세요.

  3. 수집할 봇 고르기

    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입니다. 다음 단계의 경로에 넣습니다.

  4. 수집 방법 확인하기

    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가 보입니다.

  5. 수집 요청하기

    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가 이번 수집(데이터셋)의 번호입니다. 크레딧은 수집이 데이터를 저장할 때 한 줄마다 쓰입니다(크레딧·요청 한도).

  6. 완료될 때까지 확인하기

    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은 확인이 필요한 상태(끝났지만 알림이 붙었거나 멈춘 수집)입니다.

  7. 데이터 받기

    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_...를 보내면 그대로 돌려주고, 없으면 서버가 만듭니다. 문의할 때 알려 주세요.
응답 칸설명
resultsuccess 또는 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분에 몇 번까지 부를 수 있는지는 크레딧·요청 한도를 보세요.

Python 예시
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 예시
// 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;
});

함께 보면 좋은 가이드