# 이미지 텍스트 추출(OCR)



OCR(Optical Character Recognition) 이미지 파일에서 텍스트를 추출합니다.



인증: Authorization: Bearer $APICK_API_KEY

본문 있는 REST 요청: multipart/form-data. GET 본문 및 MCP JSON-RPC 규격은 해당 명세를 따릅니다.

인증키는 서버에 보관하세요. 모든 예제는 정적 자료입니다.



## POST /rest/ocr 응답 필드

- `data` (object): 요청 처리 결과 묶음입니다. 조회한 값·작업 상태·오류 설명이 이 안에 들어 있으며, 실제 하위 필드 구성은 서비스마다 다릅니다. 값이 없으면 null·빈 배열·필드 생략 중 해당 서비스의 규칙을 따릅니다.

- `data.result` (object): 조회 결과 본문입니다. 서비스가 찾은 실제 데이터가 들어 있으며, 자료가 없거나 조회에 실패하면 null이거나 필드가 생략됩니다.

- `data.result.text_coordinate` (array): 인식한 텍스트와 위치입니다. 첫 항목은 텍스트 전체 영역이고, 두 번째 항목부터 단어 단위입니다.

- `data.result.text_coordinate[].description` (string): 인식한 텍스트입니다. 대상의 설명문입니다. 게시자·서비스가 작성한 소개문이며, 줄바꿈과 이모지가 포함될 수 있습니다. 비어 있으면 설명이 등록되지 않은 것입니다.

- `data.result.text_coordinate[].vertices` (array): 텍스트를 둘러싼 사각형의 네 꼭짓점 {x, y}입니다. 왼쪽 위부터 시계 방향이며 단위는 원본 이미지 픽셀입니다.

- `data.result.text_coordinate[].vertices[].x` (integer): 'x' 수치 값입니다. 단위·범위는 같은 응답의 다른 필드나 이 문서의 설명을 확인하세요.

- `data.result.text_coordinate[].vertices[].y` (integer): 'y' 수치 값입니다. 단위·범위는 같은 응답의 다른 필드나 이 문서의 설명을 확인하세요.

- `data.result.full_text` (string): 이미지 전체 텍스트입니다. 줄바꿈은 \n으로 들어갑니다. 문자열로 오며, 값이 없으면 빈 문자열이거나 필드가 생략됩니다. 같은 응답의 다른 필드와 함께 해석하세요.

- `data.success` (integer): 업무 처리 결과 코드입니다. 1은 정상 결과, 0은 실패 또는 무료 응답입니다. 서비스에 따라 2·3처럼 추가 코드를 쓰므로 같은 응답의 status·msg·error 필드도 함께 확인하세요.

- `api` (object): API 호출 메타데이터입니다. 이번 요청의 서버 처리 성공 여부(api.success), 실제 차감 포인트(api.cost), 결제 기록 ID(api.pl_id)를 담습니다. 처리 시간(api.ms)은 응답에 포함된 경우에만 제공됩니다. 업무 결과는 data에서 확인합니다.

- `api.success` (boolean): API 서버가 이번 요청을 정상 처리했는지 여부입니다. true여도 업무 결과가 실패일 수 있으므로 data.success·data.status와 함께 판단합니다. 인증 실패·잘못된 입력·서버 오류 응답에서는 false입니다.

- `api.cost` (integer): 이번 호출에서 실제로 차감된 포인트입니다. 유료 성공 응답에서만 단가만큼 차감되며, 실패·무료 조회·같은 요청의 멱등 재전송은 0입니다. 화면의 표시 단가와 실제 차감액이 다를 수 있으므로 정산은 이 값을 기준으로 합니다.

- `api.ms` (integer): 서버가 요청을 받아 응답 본문을 만들기까지 걸린 처리 시간(밀리초)입니다. 네트워크 왕복 시간과 클라이언트 대기 시간은 포함되지 않습니다.

- `api.pl_id` (integer): 포인트 차감 기록 ID입니다. 차감이 발생한 호출에만 값이 있으며, 과금 내역을 문의할 때 이 번호를 사용합니다. 무과금 응답은 -1·null이거나 필드가 생략됩니다.

## API 요청: POST /rest/ocr



### 입력

- `image` (file, 필수): 글자를 읽을 이미지 파일입니다. JPG·PNG를 권장하며 최대 50MB입니다. 글자가 기울지 않고 선명할수록 정확합니다.



### 응답 명세

```json

{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "result": {
          "type": "object",
          "properties": {
            "text_coordinate": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "description": {
                    "type": "string",
                    "description": "인식한 텍스트입니다."
                  },
                  "vertices": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "x": {
                          "type": "integer"
                        },
                        "y": {
                          "type": "integer"
                        }
                      }
                    },
                    "description": "텍스트를 둘러싼 사각형의 네 꼭짓점 {x, y}입니다. 왼쪽 위부터 시계 방향이며 단위는 원본 이미지 픽셀입니다."
                  }
                }
              },
              "description": "인식한 텍스트와 위치입니다. 첫 항목은 텍스트 전체 영역이고, 두 번째 항목부터 단어 단위입니다."
            },
            "full_text": {
              "type": "string",
              "description": "이미지 전체 텍스트입니다. 줄바꿈은 \\n으로 들어갑니다."
            }
          }
        },
        "success": {
          "type": "integer",
          "description": "1이면 추출 성공(과금)입니다."
        }
      }
    },
    "api": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean"
        },
        "cost": {
          "type": "integer",
          "description": "차감된 포인트입니다. 실패하면 0입니다."
        },
        "ms": {
          "type": "integer"
        },
        "pl_id": {
          "type": "integer"
        }
      }
    }
  }
}

```

### 정적 응답 예시

```json

{
  "data": {
    "result": {
      "text_coordinate": [
        {
          "description": "주민등록증\n홍길동(洪吉洞)\n900101-1234567\n서울특별시 중구 세종대로 110\n2020.08.16.\n서울특별시 중구청장",
          "vertices": [
            {
              "x": 56,
              "y": 48
            },
            {
              "x": 612,
              "y": 48
            },
            {
              "x": 612,
              "y": 423
            },
            {
              "x": 56,
              "y": 423
            }
          ]
        },
        {
          "description": "주민등록증",
          "vertices": [
            {
              "x": 109,
              "y": 48
            },
            {
              "x": 371,
              "y": 48
            },
            {
              "x": 371,
              "y": 90
            },
            {
              "x": 109,
              "y": 90
            }
          ]
        },
        {
          "description": "홍길동",
          "vertices": [
            {
              "x": 77,
              "y": 122
            },
            {
              "x": 194,
              "y": 122
            },
            {
              "x": 194,
              "y": 160
            },
            {
              "x": 77,
              "y": 160
            }
          ]
        }
      ],
      "full_text": "주민등록증\n홍길동(洪吉洞)\n900101-1234567\n서울특별시 중구 세종대로 110\n2020.08.16.\n서울특별시 중구청장"
    },
    "success": 1
  },
  "api": {
    "success": true,
    "cost": 12,
    "ms": 1450,
    "pl_id": 1234567
  }
}

```

### curl

```curl

curl --fail-with-body --request POST 'https://apick.app/rest/ocr' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form 'image=@./document.png'

```

### Node.js (서버 ESM)

```javascript

import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("image", new Blob([await readFile("./document.png")]), "document.png");
const response = await fetch("https://apick.app/rest/ocr", {
  method: "POST",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  body: form,
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
console.log(result);

```

### python

```python

import os
import requests
parts = [
    ("image", ("document.png", open("./document.png", "rb"))),
]
response = requests.request("POST", "https://apick.app/rest/ocr",
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    files=parts,
    timeout=(10, 120))
response.raise_for_status()
result = response.json()
print(result)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$form = [
    'image' => new CURLFile('./document.png'),
];
$curl = curl_init('https://apick.app/rest/ocr');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => $form,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);

```

## 사용 예시 1. 문서 이미지의 전체 텍스트 추출

스캔한 계약서·안내문에서 글자를 그대로 가져와 검색·저장할 때 씁니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/ocr' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form 'image=@./document.png'

```

- `data.result.full_text`에 줄바꿈(`\n`)이 포함된 전체 텍스트가 담깁니다.

- `data.code`가 `OCR_NO_TEXT`이면 글자가 선명한 원본으로 다시 보냅니다(과금 없음).

## 사용 예시 2. 특정 단어의 위치 찾기

영수증에서 "합계" 글자의 위치를 찾아 그 오른쪽 금액을 읽거나, 이미지 위에 강조 표시를 그릴 때 씁니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/ocr' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form 'image=@./receipt.jpg'

```

- `data.result.text_coordinate[0]`은 전체 영역이므로 단어 검색은 두 번째 항목부터 합니다.

- 찾은 항목의 `vertices` 네 점(원본 픽셀 좌표)으로 사각형을 그립니다.

## 코드·오류

- OCR_IMAGE_MISSING (400): 이미지 파일을 첨부하세요.

- OCR_UNSUPPORTED_IMAGE (400): 지원 이미지 형식을 사용하세요.

- OCR_IMAGE_TOO_LARGE (413): 50MB 이하 이미지를 사용하세요.

- OCR_NO_TEXT (422): 판독 가능한 글자가 없습니다. 선명한 이미지를 사용하세요.

- OCR_TIMEOUT (408): 처리 시간이 초과됐습니다. 이미지 크기와 품질을 확인하세요.

- OCR_CREDENTIALS_ERROR (424): 문서 처리 서비스를 일시적으로 이용할 수 없습니다. 잠시 후 다시 시도하세요. 반복되면 오류코드와 함께 문의하세요.

- OCR_CREDENTIALS_MISSING (424): 문서 처리 서비스를 일시적으로 이용할 수 없습니다. 잠시 후 다시 시도하세요. 반복되면 오류코드와 함께 문의하세요.

- OCR_UNAUTHORIZED (424): 문서 처리 서비스를 일시적으로 이용할 수 없습니다. 잠시 후 다시 시도하세요. 반복되면 오류코드와 함께 문의하세요.

- OCR_RATE_LIMITED (424): 문서 처리 서비스를 일시적으로 이용할 수 없습니다. 잠시 후 다시 시도하세요. 반복되면 오류코드와 함께 문의하세요.

- OCR_UPSTREAM_UNAVAILABLE (424): 문서 처리 서비스를 일시적으로 이용할 수 없습니다. 잠시 후 다시 시도하세요. 반복되면 오류코드와 함께 문의하세요.

- OCR_REQUEST_FAILED (424): 문서 처리 서비스를 일시적으로 이용할 수 없습니다. 잠시 후 다시 시도하세요. 반복되면 오류코드와 함께 문의하세요.

- OCR_EMPTY_RESPONSE (424): 문서 처리 서비스를 일시적으로 이용할 수 없습니다. 잠시 후 다시 시도하세요. 반복되면 오류코드와 함께 문의하세요.

## 상세 기능·요금

업로드 용량 제한: 50MB 첨부 이미지 합계는 최대 50MB입니다. 서버가 판독 가능한 크기로 최적화하며, 지나치게 큰 해상도는 정확도를 높이지 않고 처리시간만 늘릴 수 있습니다. 제한을 초과하면 HTTP 413과 REQUEST_TOO_LARGE 오류가 반환되며 과금되지 않습니다. 이용 전 확인 문서 사진, 스캔 이미지, 화면 캡처처럼 글자가 있는 이미지에서 전체 텍스트(full_text)와 단어별 위치 좌표(text_coordinate)를 추출합니다. 영수증·명함·계약서 입력 자동화, 이미지 속 특정 단어 위치 찾기에 씁니다. 텍스트를 추출한 호출 한 건당 12P가 차감됩니다. 글자를 찾지 못했거나 처리에 실패하면 data.error와 data.code로 응답하며 과금되지 않습니다. 신분증에서 이름·주민등록번호 같은 항목을 바로 뽑으려면 신분증 OCR(ocr_identi1~5)을 쓰세요. 이 API는 항목을 나누지 않고 글자 그대로 돌려줍니다.

## 상세 요청

항목설정 메서드·주소POST https://apick.app/rest/ocr 인증 헤더Authorization: Bearer — 내 계정의 API 인증키 본문 형식multipart/form-data 요청 예시 form-data 전체 예제 보기

## 상세 응답

필드타입설명 data.result.full_textstring이미지 전체 텍스트입니다. 줄바꿈은 \n으로 들어갑니다. data.result.text_coordinate[]array인식한 텍스트와 위치입니다. 첫 항목은 텍스트 전체 영역이고, 두 번째 항목부터 단어 단위입니다. data.result.text_coordinate[].descriptionstring인식한 텍스트입니다. data.result.text_coordinate[].vertices[]array텍스트를 둘러싼 사각형의 네 꼭짓점 {x, y}입니다. 왼쪽 위부터 시계 방향이며 단위는 원본 이미지 픽셀입니다. data.successinteger1이면 추출 성공(과금)입니다. api.costinteger차감된 포인트입니다. 실패하면 0입니다. { "data": { "result": { "text_coordinate": [ { "description": "주민등록증\n홍길동(洪吉洞)\n900101-1234567\n서울특별시 중구 세종대로 110\n2020.08.16.\n서울특별시 중구청장", "vertices": [ { "x": 56, "y": 48 }, { "x": 612, "y": 48 }, { "x": 612, "y": 423 }, { "x": 56, "y": 423 } ] }, { "description": "주민등록증", "vertices": [ { "x": 109, "y": 48 }, { "x": 371, "y": 48 }, { "x": 371, "y": 90 }, { "x": 109, "y": 90 } ] }, { "description": "홍길동", "vertices": [ { "x": 77, "y": 122 }, { "x": 194, "y": 122 }, { "x": 194, "y": 160 }, { "x": 77, "y": 160 } ] } ], "full_text": "주민등록증\n홍길동(洪吉洞)\n900101-1234567\n서울특별시 중구 세종대로 110\n2020.08.16.\n서울특별시 중구청장" }, "success": 1 }, "api": { "success": true, "cost": 12, "ms": 1450, "pl_id": 1234567 } } 예시는 text_coordinate의 앞 3개 항목만 보였습니다.

## 상세 코드·정책

오류 코드 실패하면 data.error(안내 문구)와 data.code가 오며 과금되지 않습니다. data.code의미대처 OCR_IMAGE_MISSINGimage 파일이 없거나 비어 있습니다.파일 필드 이름이 image인지 확인합니다. OCR_UNSUPPORTED_IMAGE이미지가 아니거나 손상됐거나 지원하지 않는 형식입니다.JPG 또는 PNG로 바꿔 다시 보냅니다. OCR_IMAGE_TOO_LARGE이미지 용량이 너무 큽니다.해상도를 줄이거나 JPG로 압축해 다시 보냅니다. OCR_NO_TEXT읽을 수 있는 글자를 찾지 못했습니다.글자가 선명한 원본 이미지로 다시 보냅니다. OCR_TIMEOUT처리 시간이 초과됐습니다.잠시 후 다시 요청합니다. 그 밖의 data.code는 일시적인 처리 오류입니다. 잠시 후 다시 요청하세요.

## 상세 예제

호출 예시 같은 요청을 JavaScript와 Python으로 옮긴 예시입니다. 키는 환경변수 APICK_API_KEY 에서 읽습니다. JavaScript 예시 form-data 전체 예제 보기 Python 예시 form-data 전체 예제 보기
