Image to Text API
Extract text from images programmatically with a single API call. Built for developers who need accurate OCR output, confidence scores, and optional text region coordinates at scale.
Why Use This API
AI OCR Extraction
Advanced AI models trained on broad visual datasets. Accurately identifies common text categories from real-world scenes.
Confidence Scoring
Returns confidence values for each detection so you can filter low-certainty predictions in production pipelines.
Text Region Output
Optionally includes text region coordinates so you can draw overlays or crop detected text.
Multi-Image to Text
extract multiple text lines and blocks within a single image. Perfect for analyzing complex designs.
Quick Start
Start identifying text in under a minute. Here's how:
- Get your API key — Sign up free to receive your key
- Send a request — POST an image containing one or more text to the endpoint
- Get the result — Receive identified text as JSON with confidence scores
curl -X POST https://precisioncounter.com/api/v1/image-to-text \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "image=@sample.png"
import requests
response = requests.post(
"https://precisioncounter.com/api/v1/image-to-text",
headers={"Authorization": "Bearer YOUR_API_KEY"},
files={"image": open("sample.png", "rb")}
)
data = response.json()
for text in data["text"]:
print(f"{text['name']} ({text['confidence']:.0%})")
const fs = require("fs");
const FormData = require("form-data");
const form = new FormData();
form.append("image", fs.createReadStream("sample.png"));
const response = await fetch(
"https://precisioncounter.com/api/v1/image-to-text",
{
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
...form.getHeaders()
},
body: form
}
);
const data = await response.json();
data.text.forEach(f => console.log(`${f.name} (${f.confidence})`));
API Reference
Base URL
https://precisioncounter.com/api/v1
Authentication
All requests require an API key passed in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Extract Text
Detects text from an uploaded image and returns structured detection results as JSON.
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| image required | file | Image file to analyze for Image to Text. Accepted formats: PNG, JPG, JPEG, WebP. Max size: 10 MB. |
| max_lines optional | integer | Max number of Image to Texts to return. Default: 5. Range: 1-20. |
| include_layout optional | boolean | Include text region coordinates for each detection. Default: true. |
Response
200 OK — Returns identified text data as JSON.
{
"text": [
{
"name": "person",
"confidence": 0.94,
"category": "person",
"box": {
"x": 124,
"y": 52,
"width": 300,
"height": 540
}
}
],
"image_width": 1280,
"image_height": 720,
"processing_time_ms": 450
}
Response Headers
| Header | Value |
|---|---|
| Content-Type | application/json |
| X-Credits-Remaining | Number of API credits remaining |
| X-Processing-Time | Processing time in milliseconds |
Code Examples
Full Examples (with error handling)
curl -X POST https://precisioncounter.com/api/v1/image-to-text \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "image=@sample.png" \
-F "max_lines=5" \
-F "include_layout=true"
import requests
import sys
API_KEY = "YOUR_API_KEY"
API_URL = "https://precisioncounter.com/api/v1/image-to-text"
def detect_text(input_path, max_lines=5):
"""Extract Text from an image file."""
with open(input_path, "rb") as img:
response = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
files={"image": img},
data={"max_lines": max_lines, "include_layout": "true"}
)
if response.status_code == 200:
data = response.json()
for text in data["text"]:
print(f"{text['name']} - {text['confidence']:.0%} confidence")
print(f" Category: {text['category']}")
if text.get("box"):
print(f" Box: {text['box']}")
print(f"Credits remaining: {response.headers.get('X-Credits-Remaining')}")
else:
print(f"Error {response.status_code}: {response.json()['error']}")
detect_text("sample.png")
const fs = require("fs");
const FormData = require("form-data");
const fetch = require("node-fetch");
const API_KEY = "YOUR_API_KEY";
const API_URL = "https://precisioncounter.com/api/v1/image-to-text";
async function detecttext(inputPath, maxResults = 5) {
const form = new FormData();
form.append("image", fs.createReadStream(inputPath));
form.append("max_lines", String(maxResults));
form.append("include_layout", "true");
const response = await fetch(API_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
...form.getHeaders()
},
body: form
});
if (response.ok) {
const data = await response.json();
data.text.forEach(text => {
console.log(`${text.name} - ${(text.confidence * 100).toFixed(0)}%`);
console.log(` Category: ${text.category}`);
if (text.box) console.log(` Box: ${JSON.stringify(text.box)}`);
});
console.log(`Credits: ${response.headers.get("x-credits-remaining")}`);
} else {
const error = await response.json();
console.error(`Error ${response.status}: ${error.error}`);
}
}
detecttext("sample.png");
<?php
$api_key = "YOUR_API_KEY";
$url = "https://precisioncounter.com/api/v1/image-to-text";
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $api_key"
],
CURLOPT_POSTFIELDS => [
"image" => new CURLFile("sample.png"),
"max_lines" => "5",
"include_layout" => "true"
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
foreach ($data["text"] as $text) {
echo $text["name"] . " - " . ($text["confidence"] * 100) . "% confidence\n";
echo " Category: " . $text["category"] . "\n";
if (isset($text["box"])) {
echo " Box: " . json_encode($text["box"]) . "\n";
}
}
} else {
echo "Error $httpCode: $response\n";
}
?>
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
type textResult struct {
Name string `json:"name"`
Confidence float64 `json:"confidence"`
Category string `json:"category"`
Box map[string]int `json:"box"`
}
type Response struct {
text []textResult `json:"text"`
ImageWidth int `json:"image_width"`
ImageHeight int `json:"image_height"`
ProcessingTime int `json:"processing_time_ms"`
}
func detecttext(inputPath string) error {
file, _ := os.Open(inputPath)
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("image", inputPath)
io.Copy(part, file)
writer.WriteField("max_lines", "5")
writer.Close()
req, _ := http.NewRequest("POST",
"https://precisioncounter.com/api/v1/image-to-text", body)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
var result Response
json.NewDecoder(resp.Body).Decode(&result)
for _, text := range result.text {
fmt.Printf("%s - %.0f%% confidence\n", text.Name, text.Confidence*100)
}
}
return nil
}
func main() {
detecttext("sample.png")
}
require "net/http"
require "uri"
require "json"
api_key = "YOUR_API_KEY"
uri = URI("https://precisioncounter.com/api/v1/image-to-text")
form_data = [
["image", File.open("sample.png", "rb")],
["max_lines", "5"],
["include_layout", "true"]
]
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{api_key}"
req.set_form(form_data, "multipart/form-data")
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
if res.code == "200"
data = JSON.parse(res.body)
data["text"].each do |text|
puts "#{text['name']} - #{(text['confidence'] * 100).round}% confidence"
puts " Category: #{text['category']}"
puts " Box: #{text['box']}" if text['box']
end
else
puts "Error #{res.code}: #{res.body}"
end
using System.Text.Json;
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_KEY");
using var form = new MultipartFormDataContent();
var imageContent = new ByteArrayContent(File.ReadAllBytes("sample.png"));
imageContent.Headers.ContentType = new("image/png");
form.Add(imageContent, "image", "sample.png");
form.Add(new StringContent("5"), "max_lines");
form.Add(new StringContent("true"), "include_layout");
var response = await client.PostAsync(
"https://precisioncounter.com/api/v1/image-to-text", form);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize<JsonElement>(json);
foreach (var text in data.GetProperty("text").EnumerateArray())
{
Console.WriteLine($"{text.GetProperty("name")} - {text.GetProperty("confidence")}");
}
}
Error Handling
The API returns standard HTTP status codes with JSON error bodies:
| Status | Meaning | Description |
|---|---|---|
| 200 | Success | text identified successfully. Response body contains JSON with text data. |
| 400 | Bad Request | Missing image file, unsupported format, or file too large. |
| 401 | Unauthorized | Missing or invalid API key. |
| 429 | Rate Limited | Too many requests. Wait and retry with exponential backoff. |
| 500 | Server Error | Internal processing error. Retry the request. |
Error Response Format
{
"error": "Invalid file format. Accepted: png, jpg, jpeg, webp",
"code": "INVALID_FORMAT",
"status": 400
}
Rate Limits
| Plan | Requests / Minute | Max File Size | Max Resolution |
|---|---|---|---|
| Free | 10 | 10 MB | 4096 x 4096 px |
| Pro | 60 | 25 MB | 8192 x 8192 px |
Rate limit headers are included in every response:
X-RateLimit-Limit: 10 X-RateLimit-Remaining: 7 X-RateLimit-Reset: 1708646400
Use Cases
- Design asset management
- Brand consistency checking
- Web scraping Image to Text
- Accessibility compliance
- Print production
- image analysis research
- Design tool plugins
- detection workflow verification
Pricing
Get free API credits when you sign up. No credit card required.
Frequently Asked Questions
max_lines parameter to control how many Image to Texts are returned, up to 20 per request.include_layout parameter set to false.