확인할 수 있는 데이터로 바꾸는 PDF OCR
space-ocr로 PDF 페이지에서 구조화 데이터를 추출합니다. 필요한 필드를 선언하면 각 값이 data.cells의 좌표와 함께 반환되고, 확인할 항목은 data.review.flagged에 모입니다.
PDF는 데이터가 숨어버리는 곳입니다. 세금계산서, 영수증 더미, 납품서 — 숫자는 분명 페이지에 있는데, 스프레드시트로 옮기려면 결국 다시 입력하게 됩니다. PDF OCR은 이를 해결하겠다고 약속합니다. 문서를 읽어 구조화된 필드를 돌려준다는 거죠. 문제는 대부분의 도구가 그럴듯한 추측에서 멈추고, 나머지는 그냥 믿으라고 한다는 점입니다.
space-ocr는 더 엄격한 질문에 답합니다. 필요한 필드를 선언하면 각 값이 읽어낸 페이지 영역 — data.cells 의 box 와 quad — 과 함께 돌아오고, 대조가 통과하지 못한 경로는 data.review.flagged 에 모입니다. 해석해야 할 점수 하나가 아니라, 확인할 작업 목록이 옵니다.
직접 검증할 수 있는 실제 추출 결과
아래 어느 항목이든 마우스를 올려 보세요 — 영수증 위의 박스가 그 값을 읽어낸 지점입니다. 여기 있는 값·박스·일치율은 모두 실제 파싱 결과에서 읽어온 것으로, 목업이 아닙니다.

Each value with a box carries a verified on-page location — in data.cells[path], that is box + 4-point quad + evidence.match_ratio — on a 0–1000 normalized grid (0,0 top-left → 1000,1000 bottom-right), the same shape the live API returns. Hover a field to trace it back to the pixels it came from.
space-ocr의 PDF OCR 작동 방식
앱에 PDF를 끌어다 놓으면 각 페이지가 브라우저에서 PNG로 렌더링되고, 읽혀서 구조화된 필드가 됩니다 — 여러 페이지 PDF는 정렬·필터·내보내기가 가능한 행의 모음이 됩니다.
공개 API는 더 엄격해서 래스터 이미지만 읽고 PDF 바이트는 읽지 않습니다. POST /upload 는 PDF를 그 자리에서 거절하며 페이지를 먼저 이미지로 만들라고 알려 줍니다. API를 쓸 때는 직접 래스터화한 페이지 이미지를 보내세요. 어느 경로든 1페이지가 1크레딧입니다.
/ocr/fields 응답은 다음과 같습니다.
data.values— 선언한 스키마 그대로의 업무 데이터.data.cells[path]— 그 경로의box·quad·verified·review·evidence.data.review—declared·returned·boxed·verified, 그리고 작업 목록인flagged.data.normalized—number·integer·date를 선언한 필드의 파싱된 값.data.image— 모든 좌표의 기준이 되는 폭과 높이.
verified 는 글자 일치 결과가 아니라 판정입니다. review 에 사유가 서면 false, 대조가 돌았는데 아무것도 서지 않으면 true, 대조할 대상이 없으면 null 입니다. 글자 대조 자체는 evidence.text_match 에 있고, evidence.match_ratio 는 그 옆의 보조 근거입니다.
# API가 읽는 것은 이미지이지 PDF 바이트가 아니다 — 페이지를 먼저 이미지로 만든다
pdftoppm -r 200 -jpeg invoice.pdf page
curl -s https://api.space-ocr.com/ocr/fields \
-H "Authorization: Bearer $SPACE_OCR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image": "https://example.com/page-1.jpg",
"imageType": "url",
"fields": [
{ "name": "invoice_no", "type": "string", "required": true },
{ "name": "issue_date", "type": "date", "required": true },
{ "name": "total", "type": "number", "required": true, "min": 0 },
{ "name": "items", "type": "array", "children": [
{ "name": "description", "type": "string" },
{ "name": "quantity", "type": "number" },
{ "name": "amount", "type": "number" }
] }
]
}'PDF를 OCR하는 방법
- 페이지를 이미지로 만들기웹 앱에서는 PDF를 끌어다 놓으면 각 페이지가 브라우저에서 PNG로 렌더링됩니다. API를 직접 호출한다면 페이지를 직접 래스터화해 url 또는 base64로 POST /ocr/fields 에 보내거나, POST /upload 로 시트에 올립니다.
- 필드 선언하기필요한 fields 를 나열합니다. name 과 type 에 더해 상황에 맞게 required·pattern·min/max·enum·label·near 를 선언합니다. 품목 표에는 children 이 있는 array 필드를 쓰고, 양식이 낯설면 autoFields: true 로 스키마를 제안받습니다.
- 구조화 결과 읽기업무 데이터는 선언한 스키마 그대로 data.values 에, 경로별 box·quad·verified·review·evidence 는 data.cells[path] 에, number·integer·date 를 선언한 필드의 파싱 값은 data.normalized 에 담깁니다.
- review.flagged 처리하기data.review.flagged 를 순회합니다. 각 항목은 path 와 랭킹 순 reasons 배열이며 0번이 대표 사유입니다. data.cells[path] 를 열어 box 또는 quad 를 data.image 기준으로 그리고, 값을 읽어낸 영역 옆에서 바로 고칩니다.
- 내보내기 또는 조회CSV(UTF-8 BOM, 품목 펼쳐짐)를 다운로드하거나, 저장된 시트를 GET /view 로 where·sort·select·boxes 를 써서 조회합니다 — 이 조회는 무료이며 OCR을 다시 돌리지 않습니다.
단순하고 예측 가능한 가격
1크레딧이 1페이지, ₩100(부가세 포함)입니다. 모든 계정에 매월 100크레딧 무료 제공, 카드 등록 없이 시작하고 실패는 과금하지 않습니다. 정액 플랜은 월 크레딧·시트·저장공간을 추가합니다.