KYC 없음 — 신분증도, 셀피도, 서류도 없습니다. 암호화폐로 결제하세요: BTC, USDT, USDC, ETH, SOL, LTC
언어: 한국어
API 키 발급받기

문서 · 작업

Batch 및 crawl API: 여러 URL 또는 사이트 전체 읽기

두 endpoint가 백그라운드 작업을 시작합니다: /batch은 최대 100개 URL 목록용, /crawl은 하나의 웹사이트용입니다. 둘 다 작업 ID를 반환하며, /jobs/{job_id}에서 한 번에 한 페이지씩 결과를 수집합니다.

마지막 업데이트: · 6 분 읽기

빠른 답변

WebReaderAPI로 웹사이트를 Markdown으로 크롤링하려면 어떻게 하나요?

시작 URL을 페이지 limit와 함께 POST https://webreaderapi.com/api/v1/crawl로 보내세요. WebReaderAPI은 백그라운드에서 사이트를 읽으며, 같은 도메인만, sitemap, robots.txt 및 Crawl-delay를 따라 작업당 최대 10,000페이지까지 처리합니다. 작업에서 Markdown 페이지를 한 번에 한 페이지씩 수집하세요. 페이지 읽기마다 1크레딧(브라우저 사용 시 2크레딧)이 들며, 2026년 10월 기준 US$0.07/1K 페이지입니다. KYC 없이 암호화폐 결제.

작업 한눈에 보기

Batch배치 작업당 최대 100개의 URL: POST https://webreaderapi.com/api/v1/batch
크롤링작업당 웹사이트 하나를 크롤링하며, 최대 10,000페이지까지 사이트맵, robots.txt 및 Crawl-delay를 따릅니다: POST https://webreaderapi.com/api/v1/crawl
결과GET https://webreaderapi.com/api/v1/jobs/{job_id}, 다음 결과 페이지는 ?cursor=…
과금페이지 읽기마다 /read 호출과 동일하게 과금됩니다; robots.txt에서 건너뛴 페이지와 실패한 페이지는 무료입니다
크롤링 범위하나의 도메인; 다른 도메인으로의 링크는 나열되지만 읽지 않습니다
작업 취소v1에서는 제공되지 않습니다: 지불할 준비가 된 최대 페이지 수를 limit에 설정하세요

Batch 작업 시작

POST/api/v1/batch

동일한 옵션으로 최대 100개 URL을 백그라운드에서 읽습니다. 옵션은 /read의 이름과 값을 사용합니다. 응답은 작업 ID이며, 값은 예시입니다.

인증: Authorization: Bearer API_KEY 헤더에 API 키를 넣습니다.

요청 본문

필드타입필수설명
urlsarray of strings예http 또는 https URL 1~100개. 중복된 URL은 한 번만 읽습니다.
optionsobject아니요url을 제외한 모든 /read 파라미터: format, main_content, render, include_links, include_images, country, max_chars, timeout.
예시: three articles as Markdown
{
  "urls": [
    "https://example.com/blog/post-1",
    "https://example.com/blog/post-2",
    "https://example.org/news/launch"
  ],
  "options": {
    "format": "markdown",
    "max_chars": 50000
  }
}

응답 202 Accepted

{
  "job_id": "job_5c1e8a90d2"
}

코드 예제

curl
curl -s "https://webreaderapi.com/api/v1/batch" \
  -H "Authorization: Bearer $WEBREADER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://example.com/blog/post-1", "https://example.com/blog/post-2"], "options": {"format": "markdown"}}'
Python
import os
import requests

resp = requests.post(
    "https://webreaderapi.com/api/v1/batch",
    headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
    json={"urls": ["https://example.com/blog/post-1", "https://example.com/blog/post-2"], "options": {"format": "markdown"}},
    timeout=30,
)
print(resp.json()["job_id"])
Node.js
const res = await fetch('https://webreaderapi.com/api/v1/batch', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ urls: ['https://example.com/blog/post-1', 'https://example.com/blog/post-2'], options: { format: 'markdown' } }),
});
console.log((await res.json()).job_id);

크롤링 작업 시작

POST/api/v1/crawl

시작 URL에서 한 웹사이트를 너비 우선 방식으로 읽습니다. 크롤러는 시작 URL의 도메인에 머물고, robots.txt에 명시되었거나 /sitemap.xml에서 발견된 sitemap을 사용하며, robots.txt와 Crawl-delay를 준수합니다. 값은 예시입니다.

인증: Authorization: Bearer API_KEY 헤더에 API 키를 넣습니다.

요청 본문

필드타입필수설명
urlstring예시작 페이지입니다. 예를 들어 문서 사이트의 홈페이지입니다.
limitinteger아니요읽을 최대 페이지 수이며 최대 10,000까지입니다. 작업은 이 수에 도달하면 중지됩니다.
max_depthinteger아니요시작 URL에서 떨어진 최대 링크 단계 수입니다.
include_pathsarray of strings아니요유지할 단순 경로 패턴입니다. 예: /docs/*.
exclude_pathsarray of strings아니요건너뛸 단순 경로 패턴입니다. 예: /blog/tag/*.
optionsobject아니요url을 제외한 모든 /read 파라미터로, 모든 페이지에 적용됩니다.
예시: the docs section of a site, 500 pages at most
{
  "url": "https://docs.example.com/",
  "limit": 500,
  "max_depth": 3,
  "include_paths": [
    "/docs/*"
  ],
  "exclude_paths": [
    "/docs/archive/*"
  ],
  "options": {
    "format": "markdown"
  }
}

응답 202 Accepted

{
  "job_id": "job_8b27f41c0e"
}

코드 예제

curl
curl -s "https://webreaderapi.com/api/v1/crawl" \
  -H "Authorization: Bearer $WEBREADER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://docs.example.com/", "limit": 500, "include_paths": ["/docs/*"]}'
Python
import os
import requests

resp = requests.post(
    "https://webreaderapi.com/api/v1/crawl",
    headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
    json={"url": "https://docs.example.com/", "limit": 500, "include_paths": ["/docs/*"]},
    timeout=30,
)
print(resp.json()["job_id"])
Node.js
const res = await fetch('https://webreaderapi.com/api/v1/crawl', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ url: 'https://docs.example.com/', limit: 500, include_paths: ['/docs/*'] }),
});
console.log((await res.json()).job_id);

작업 상태와 결과 가져오기

GET/api/v1/jobs/{job_id}

작업의 상태와 준비된 다음 결과를 반환합니다. results의 각 항목은 전체 /read 응답이거나 읽을 수 없는 페이지에 대한 {url, error}입니다. next_cursor이 있으면 cursor를 해당 값으로 설정해 다시 호출하세요. 없으면 아직 준비된 결과가 더 없다는 뜻입니다. 값은 예시입니다.

인증: Authorization: Bearer API_KEY 헤더에 API 키를 넣습니다.

파라미터

이름위치타입필수설명
job_idpathstring예/batch 또는 /crawl이 반환한 ID입니다.
cursorquerystring아니요다음 결과를 받기 위해 이전 호출에서 받은 next_cursor 값입니다.

응답 200

{
  "job_id": "job_8b27f41c0e",
  "status": "running",
  "results": [
    {
      "url": "https://docs.example.com/docs/install",
      "final_url": "https://docs.example.com/docs/install",
      "status_code": 200,
      "rendered": false,
      "credits_used": 1,
      "title": "Install",
      "markdown": "# Install\n\nRun the installer...",
      "word_count": 418
    },
    {
      "url": "https://docs.example.com/docs/private",
      "error": {
        "code": "blocked_by_robots",
        "message": "robots.txt disallows this page for WebReaderAPI."
      }
    }
  ],
  "next_cursor": "c_000002",
  "credits_used": 1
}

코드 예제

curl
curl -sG "https://webreaderapi.com/api/v1/jobs/job_8b27f41c0e" \
  -H "Authorization: Bearer $WEBREADER_API_KEY" \
  -d cursor=c_000002
Python
import os
import requests

resp = requests.get(
    "https://webreaderapi.com/api/v1/jobs/job_8b27f41c0e",
    headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
    params={"cursor": "c_000002"},
    timeout=30,
)
job = resp.json()
print(job["status"], len(job["results"]), job.get("next_cursor"))
Node.js
const res = await fetch('https://webreaderapi.com/api/v1/jobs/job_8b27f41c0e?cursor=c_000002', {
  headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}` },
});
const job = await res.json();
console.log(job.status, job.results.length, job.next_cursor);

작업이 끝날 때까지 어떻게 기다리나요?

/jobs/{job_id}를 폴링하고 커서를 보관하세요. 받은 결과를 처리한 다음 cursor를 next_cursor 값으로 설정해 다시 호출합니다. next_cursor가 없고 status가 done이면 모든 결과를 받은 것이고, next_cursor가 없는데 작업이 아직 running 상태라면 잠시 기다린 뒤 같은 커서로 다시 요청하세요.

처음에는 2초마다 폴링하고, 새 결과가 없는 동안에는 대기 시간을 최대 30초까지 두 배씩 늘리세요. 사이트의 Crawl-delay를 지키는 크롤링은 시간이 걸릴 수 있으므로 오래 기다리는 것은 정상이며 비용이 들지 않습니다.

Python: 작업을 폴링하고 모든 페이지를 .md 파일로 저장
import os
import pathlib
import re
import time

import requests

JOBS = "https://webreaderapi.com/api/v1/jobs"
HEADERS = {"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]}


def save_job(job_id, folder="pages"):
    out = pathlib.Path(folder)
    out.mkdir(exist_ok=True)
    cursor, wait, saved = None, 2, 0
    while True:
        params = {"cursor": cursor} if cursor else {}
        job = requests.get(f"{JOBS}/{job_id}", headers=HEADERS, params=params, timeout=30).json()
        for item in job["results"]:
            if "error" in item:
                print("skipped", item["url"], item["error"]["code"])
                continue
            name = re.sub(r"[^a-z0-9]+", "-", item["final_url"].lower()).strip("-")[:120]
            (out / f"{name}.md").write_text(item["markdown"], encoding="utf-8")
            saved += 1
        if job.get("next_cursor"):
            cursor, wait = job["next_cursor"], 2
            continue
        if job["status"] == "done":
            return saved
        time.sleep(wait)
        wait = min(wait * 2, 30)


if __name__ == "__main__":
    print(save_job("job_8b27f41c0e"), "pages saved")

크롤링은 어떤 페이지를 읽나요?

크롤링은 지정한 URL에서 시작해 한 번에 링크 한 단계씩, 너비 우선(breadth first) 방식으로 최대 max_depth까지 바깥으로 확장됩니다. 또한 robots.txt에 명시된 주소나 /sitemap.xml에서 사이트의 sitemap을 읽어 링크가 거의 연결되지 않은 페이지도 찾아냅니다.

  • 동일 도메인만. 다른 도메인으로 향하는 링크는 include_links를 요청할 때 결과에 나열되지만, 읽지는 않습니다.
  • 경로 필터. include_paths과 exclude_paths는 /blog/* 같은 단순한 패턴을 받습니다.
  • 페이지당 한 번만. 사이트가 canonical URL을 선언하면 여러 주소로 접근되는 페이지는 한 번만 읽습니다.
  • 확실한 종료 조건. 작업은 limit개의 페이지를 읽으면 종료됩니다.

크롤링은 사이트를 어떻게 존중하나요?

모든 요청에는 User-Agent WebReaderAPI/1.0 (+https://webreaderapi.com/bot/)가 함께 전송되며, 크롤러는 WebReaderAPI에 대한 robots.txt 규칙을 따르고, 해당 이름을 명시한 규칙이 없으면 모든 로봇에 대한 규칙을 따릅니다. 허용되지 않은 페이지는 건너뛰며 results에 오류 blocked_by_robots과 함께 나타나고, 크레딧이 차감되지 않습니다.

robots.txt에 Crawl-delay이 설정되어 있으면 크롤러는 해당 사이트에 요청을 보낼 때마다 그 시간만큼 기다립니다. 사이트가 robots.txt에 Content-Signal: ai-input=no를 선언하면, 해당 페이지를 대신 읽지 않습니다. 사이트가 우리 요청을 거부하면 그 응답을 그대로 반환합니다. 우리는 CAPTCHA를 풀거나, 계정에 로그인하거나, 차단이나 페이월을 우회하려 시도하지 않습니다.

크롤링 비용은 얼마인가요?

페이지를 읽을 때마다 /read 호출과 같은 비용이 듭니다. 즉 1 크레딧이고, 페이지에 브라우저가 필요했다면 2 크레딧이며, country을 사용하면 10 크레딧이 추가됩니다. 건너뛴 페이지와 실패한 페이지는 무료입니다. 작업의 credits_used에는 지금까지 청구된 금액이 합산됩니다.

브라우저 없이 500페이지 분량의 문서 사이트를 읽으면 약 500 크레딧을 사용하며, 10,000페이지 팩(US$3.75)으로 여러 번 충당할 수 있습니다. v1에서는 작업을 취소할 수 없으므로 limit가 지출 한도입니다. 지불할 의사가 있는 최대 페이지 수로 설정하세요.

배치와 크롤링: 자주 묻는 질문

/batch를 사용해야 하나요, 아니면 /read를 여러 번 호출해야 하나요?

이미 URL이 있고 각 응답을 즉시 받을 필요가 없다면 /batch을 사용하세요. 동시성과 재시도를 직접 관리할 필요가 없습니다. 에이전트가 지금 바로 한 페이지를 필요로 한다면 /read을 사용하세요.

작업 결과는 얼마나 보관되나요?

준비되는 즉시 결과를 수집하세요. 결과는 가져올 때까지 대기하며, 전달된 후에는 페이지 콘텐츠의 사본이 보관되지 않으므로 필요한 내용은 직접 저장하세요.

크롤링이 다른 웹사이트로 연결되는 링크를 따라갈 수 있나요?

아니요. 크롤링은 하나의 도메인만 읽습니다. 다른 도메인은 요청할 경우 링크로 나타나며, 해당 URL을 읽고 싶다면 /batch으로 보낼 수 있습니다.

시작된 크롤링을 중지할 수 있나요?

v1에서는 할 수 없습니다. 작업은 limit페이지에서 멈추므로 예산에 맞는 한도를 선택하세요. 이미 읽은 페이지는 계속 청구되며, 읽지 않은 페이지는 무료입니다.

US$0.07/1K 페이지부터 · KYC 없이

API 키 발급받기