
Huntsman은 웹페이지를 가져와 광고와 탐색 메뉴 등을 걸러낸 뒤 대형언어모델(LLM)과 검색에 쓸 마크다운으로 변환하는 자체 호스팅 스크래퍼다. JavaScript 페이지를 렌더링하고 Firecrawl 호환 API를 제공하며, 프로젝트는 같은 8-vCPU 환경에서 Firecrawl보다 초당 4배 많은 페이지를 처리한다고 주장한다.
기능과 사용 범위
Huntsman은 Go 바이너리 하나와 컨테이너 하나로 실행된다. Redis, Playwright, Chrome은 필요하지 않으며, JavaScript 렌더링에는 Lightpanda를 사용한다. 페이지가 조용해질 때까지 기다린 뒤 내용을 추출하고, PDF는 직접 가져온다. 헤드리스 브라우저를 차단하는 페이지는 일반 HTML 방식으로 다시 시도한다.
도구는 Firecrawl의 onlyMainContent 규칙과 EasyList 필터를 사용해 주요 본문을 남기고 탐색 메뉴, 푸터, 광고, 쿠키 배너를 제거한다. Firecrawl의 /v1 요청·응답 형식을 따르므로 대부분의 클라이언트는 기본 URL만 바꾸면 된다. 결과 캐시와 호스트별 동시 요청 제한이 있는 SQLite 기반 대기열은 배치 요청 최대 1,000개와 사이트 전체 크롤링을 지원한다.
보안 관련 기본 설정으로는 연결 시점에 비공개·루프백·링크 로컬 주소를 차단하고 robots.txt를 준수하며, 루트가 아닌 사용자로 실행하는 기능이 있다. 전달자 토큰 인증도 지원한다.
Firecrawl에서 옮겨올 때는 클라이언트의 기본 URL을 Huntsman 주소로 바꾸고 /v1/scrape를 계속 사용하면 된다. 다만 Huntsman은 마크다운과 링크만 반환한다. 스크린샷, HTML, JSON 추출, 액션, 검색 기능은 제공하지 않는다. 검색 기능이 필요하면 SearXNG 같은 검색 엔진과 함께 사용할 수 있다.
설치와 API
공개된 Docker 이미지는 linux/amd64와 linux/arm64를 지원한다. 빠른 실행 명령은 다음과 같다.
docker run -d --name huntsman -p 127.0.0.1:8080:8080 -v huntsman-data:/data ghcr.io/tulipfarm/huntsman:latest
페이지를 가져오려면 다음 요청을 보낸다.
curl -s localhost:8080/v1/scrape \\
-H 'Content-Type: application/json' \\
-d '{"url": "https://example.com"}'
저장소에는 이 요청의 예시 응답도 포함돼 있다. 응답은 success, 작업 id, 캐시 사용 여부를 나타내는 cached와 함께 페이지의 markdown, 링크 목록, 제목·원본 URL·상태 코드·가져온 시각·사용 엔진을 담은 메타데이터를 반환한다. 예시에서는 엔진이 lightpanda로 표시된다.
실서비스에서는 latest 대신 ghcr.io/tulipfarm/huntsman:0.1.0 같은 버전 태그나 이미지 다이제스트를 고정하고, HUNTSMAN_TOKEN 또는 HUNTSMAN_TOKENS를 설정하라고 프로젝트는 안내한다. 소스에서 빌드할 때는 다음 명령을 사용한다.
git clone https://github.com/TulipFarm/huntsman.git && cd huntsman
docker compose up -d --build
제공하는 API는 다음과 같다.
| 엔드포인트 | 기능 |
|---|---|
POST /v1/scrape | URL 하나를 스크랩해 markdown과 links를 반환한다. |
POST /v1/batch | URL 1~1,000개를 대기열에 넣는다. 요청 형식은 {"urls": [...], "scrapeOptions": {...}}다. |
GET /v1/jobs/{id} | 대기열 작업의 상태와 결과를 조회한다. |
POST /v1/crawl | 사이트를 크롤링한다. 요청에는 {"url", "limit", "maxDepth", "scrapeOptions"}를 넣는다. |
GET /v1/crawl/{id}?offset=N | 크롤링 진행 상황과 페이지를 조회한다. |
GET /health | 서비스 생존 여부와 저장소 상태를 확인한다. |
스크랩 옵션은 url, formats(마크다운만 지원), waitFor(밀리초), waitSelector, timeout(밀리초), maxAge(밀리초 단위 캐시 기간), onlyMainContent다. 알 수 없는 필드는 거부하므로 오타가 있어도 조용히 무시되지 않는다.
HUNTSMAN_TOKEN 또는 HUNTSMAN_TOKENS를 설정하면 /health를 제외한 모든 엔드포인트에 Authorization: Bearer <token> 인증이 필요하다. HUNTSMAN_TOKENS를 사용하면 클라이언트별 키를 지정할 수 있다. 예를 들어 HUNTSMAN_TOKENS=web:t0k3n1,staging:t0k3n2처럼 설정한다. 요청 로그에는 토큰 자체가 아니라 키 이름만 기록되므로, 클라이언트를 구분하고 다른 키에 영향을 주지 않으면서 특정 키를 폐기할 수 있다고 프로젝트는 설명한다.
사이트 크롤링은 다음과 같이 시작한다.
curl -s localhost:8080/v1/crawl \\
-H 'Content-Type: application/json' \\
-d '{"url": "https://example.com", "limit": 50, "maxDepth": 2}'
# → {"success": true, "id": "…"}
curl -s 'localhost:8080/v1/crawl/<id>?offset=0'
성능 비교와 조건
프로젝트가 공개한 벤치마크는 각 엔진을 별도 AWS Graviton(ARM) 머신에서 자체 호스팅하고, 데이터셋 테스트 분할에서 뽑은 URL 1,000개를 처리한 결과다. 각 수치는 통과한 최대 동시 페이지 수, 그 수준에서의 초당 페이지 수, 성공률 순으로 표시한다.
| 머신 | Huntsman | Firecrawl | Crawl4AI |
|---|---|---|---|
| 소형(2 vCPU, 4 GB) | 45 · 4.58/s · 90.9% | 8 · 0.91/s · 92.5% | 2에서도 실패 |
| 중형(4 vCPU, 8 GB) | 75 · 7.74/s · 91.8% | 15 · 1.58/s · 92.2% | 15 · 1.35/s · 80.6% |
| 대형(8 vCPU, 16 GB) | 129 · 11.54/s · 90.8% | 43 · 2.90/s · 92.3% | 22 · 1.62/s · 81.8% |
프로젝트의 기준에서 한 단계가 통과하려면 엔진이 충돌하거나 메모리 부족을 일으키지 않아야 하고, 성공률이 해당 엔진의 최고 성공률보다 10%포인트 넘게 낮아지지 않아야 한다. 중앙 페이지 처리 시간도 동시 처리 8페이지일 때의 3배 이하여야 한다. 이 기준에 따른 최대치는 이분 탐색으로 찾았다. Huntsman은 매번 페이지 처리 시간이 기준에 도달해 시험을 멈췄고, 모든 CPU 코어를 사용했으며 충돌이나 메모리 부족은 발생하지 않았다고 프로젝트는 밝혔다.
각 수치는 실제 사이트를 대상으로 한 단일 실행 결과다. 모든 엔진에서 robots.txt 확인을 끄고, Firecrawl은 스크랩 전용 모드로 실행했다. 방법과 원자료는 benchmark/README.md와 benchmark/results/에 공개돼 있다.
벤치마크 데이터셋 huntsman-scrape-dataset-v1은 CC BY 4.0 라이선스로 Hugging Face에 올라와 있다. 63개 언어를 대상으로 문자 진행 방향, 렌더링 방식, 페이지 유형, 지역, 주제를 고려해 균형을 맞춘 URL 10,000개를 담았다. 데이터셋 생성 파이프라인은 dataset/huntsman-v1/에서 확인할 수 있다.
설정과 개발
모든 설정은 환경 변수로 지정한다.
| 변수 | 기본값 | 설명 |
|---|---|---|
HUNTSMAN_ADDR | 127.0.0.1:8080 (Docker에서는 0.0.0.0:8080) | 수신 주소 |
HUNTSMAN_WORKERS | CPU당 16개, 메모리 ÷ 96 MB로 상한 설정 | 브라우저 인스턴스 수, 즉 동시에 렌더링하는 페이지 수. 컨테이너의 CPU·메모리 제한을 반영한다. |
HUNTSMAN_PER_HOST | 2 | 호스트별 동시 페이지 수 |
HUNTSMAN_QUEUE_CAPACITY | 10000 | 429 응답을 반환하기 전까지 대기열에 넣을 작업 수 |
HUNTSMAN_CACHE_TTL | 1h | 기본 결과 캐시 기간. 최대 168h다. |
HUNTSMAN_TOKEN | 비어 있음 | 전달자 토큰. 비어 있으면 인증을 사용하지 않는다. |
HUNTSMAN_TOKENS | 비어 있음 | name:token,... 형식의 이름 있는 토큰. HUNTSMAN_TOKEN 대신 사용한다. |
HUNTSMAN_OBEY_ROBOTS | true | robots.txt 준수 여부 |
HUNTSMAN_ALLOW_PRIVATE | false | 비공개·루프백 주소 허용 여부 |
HUNTSMAN_IDLE_MS | 200 | 내용을 추출하기 전 네트워크 유휴 대기 시간 |
HUNTSMAN_ADBLOCK_LISTS | Docker에서 EasyList, EasyPrivacy, Fanboy Cookiemonster | 쉼표로 구분하는 필터 목록 파일 |
HUNTSMAN_DB | data/huntsman.db | SQLite 대기열과 캐시 경로 |
HUNTSMAN_BROWSER | lightpanda | 브라우저 바이너리 |
HUNTSMAN_BROWSER_PORT | 9222 | 첫 CDP 포트. 작업자 i는 포트에 i를 더한 값을 사용한다. |
저장소는 스크래퍼인 cmd/huntsman 서버와 internal/engine, Firecrawl·Crawl4AI·Spider와 속도·메모리·정확도를 비교하는 benchmark/, URL 벤치마크 데이터셋과 평가 도구가 있는 dataset/, Astro로 만든 site/로 구성된다.
개발에는 Go가 필요하며, 브라우저 테스트를 하려면 Lightpanda 바이너리도 필요하다. 기본 빌드와 테스트 명령은 다음과 같다. 브라우저가 없으면 브라우저 테스트는 건너뛴다.
go build ./...
go test ./... # browser tests are skipped without a browser
HUNTSMAN_TEST_BROWSER=/path/to/lightpanda go test ./...
docker build --target test . # full test suite with Lightpanda inside Docker
릴리스와 라이선스
유지관리자는 자신의 컴퓨터에서 릴리스를 시작하고, 빌드는 GitHub Actions에서 진행한다. 버전과 릴리스 노트를 미리 보려면 GitHub CLI와 선택 사항인 git-cliff가 필요하다. 다음 명령은 커밋 메시지를 기준으로 버전을 정한다. 1.0 이전에는 feat가 마이너 버전, fix가 패치 버전에 해당한다.
make release # version from the commit messages: feat → minor (before 1.0), fix → patch
make release BUMP=minor # or patch, major, or an exact version such as 1.0.0
명령은 main에서 CI가 통과했는지 확인하고 변경 사항과 다음 버전을 보여준 뒤 릴리스 워크플로 시작 여부를 묻는다. 워크플로는 다음 작업을 수행한다.
CHANGELOG.md를 작성해main에 커밋하고vX.Y.Z태그를 붙인다.- Docker 테스트 모음을 실행한다.
- 출처 증명(attestation)과 소프트웨어 자재 명세서(SBOM)를 포함해
ghcr.io/tulipfarm/huntsman이미지를linux/amd64,linux/arm64용으로 빌드하고X.Y.Z,X.Y,latest태그로 게시한다. - 커밋과 태그를 푸시하고 GitHub 릴리스를 만든다.
명령을 실행한 스크립트는 워크플로가 끝날 때까지 진행 상황을 확인한다. 이슈와 풀 리퀘스트 제출은 환영하며, 기여 전에는 CONTRIBUTING.md와 Code of Conduct를 읽어야 한다. 취약점은 SECURITY.md에 설명된 방식으로 비공개 보고하도록 안내한다.
Huntsman은 Apache-2.0 라이선스를 따른다. Docker 이미지에는 별도 라이선스를 따르는 구성 요소도 들어 있다. 별도 프로세스로 수정 없이 실행되는 Lightpanda 브라우저는 AGPL-3.0, EasyList 필터 목록은 GPLv3 / CC BY-SA 3.0 라이선스를 사용한다. Firecrawl 데이터셋은 MIT, Huntsman 데이터셋은 CC BY 4.0 라이선스다. 자세한 내용은 NOTICE에 있다. 프로젝트는 TulipFarm이 만들었다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요