CamScanner provides image translation: detect text in images, translate to the target language, and render translated text preserving the original layout. The workflow is a 3-step pipeline: upload the image, translate it, then download the result.
Important: Privacy & Data Flow Notice
- Third-party service: This skill sends your files to CamScanner's official servers (
ai-tools.camscanner.com) for processing.- Data retention: CamScanner servers process your files in real-time. Files are not permanently stored on the server.
- Local files: Output files are saved to your local filesystem at the path you specify.
Base URL: https://ai-tools.camscanner.com
to parameter)#The to parameter specifies the target language code. Determine it from the user's intent.
Common language mapping (use this first):
User says (English)User says (Chinese)to codeEnglish英语/英文enChinese Simplified简体中文/中文zh-HansChinese Traditional繁体中文zh-HantCantonese粤语yueJapanese日语/日文jaKorean韩语/韩文koFrench法语/法文frGerman德语/德文deSpanish西班牙语esPortuguese葡萄牙语ptRussian俄语/俄文ruArabic阿拉伯语arItalian意大利语itDutch荷兰语nlThai泰语/泰文thVietnamese越南语viIndonesian印尼语idMalay马来语msTurkish土耳其语trPolish波兰语plSwedish瑞典语svDanish丹麦语daHindi印地语hiBengali/Bangla孟加拉语bnUkrainian乌克兰语ukCzech捷克语csGreek希腊语elHebrew希伯来语heFinnish芬兰语fiHungarian匈牙利语hu
If the target language is NOT in the table above, look up the language code dynamically:
bash
LANG_DATA=$(curl -sS "https://open.camscanner.com/sync/get_languages")
# Parse LANG_DATA to find the matching language code by name or chineseName
# Example: find code for "Romanian"
TO=$(echo "$LANG_DATA" | jq -r '.data | to_entries[] | select(.value.name == "Romanian" or .value.chineseName == "罗马尼亚语") | .key')
The API returns all supported languages with name (English), nativeName, and chineseName (Chinese) fields.
bash
BASE="https://ai-tools.camscanner.com"
IN_FILE_ID=$(curl -sS -X POST "$BASE/v1/tools/upload_file/execute" \
-H "Content-Type: application/octet-stream" \
--data-binary "@/path/to/image.png" | jq -r '.tool_result.data.file_id')
Response:
json
{
"code": 200,
"tool": "upload_file",
"tool_result": {
"success": true,
"data": {
"file_id": "file_1741857600_ab12cd34ef56",
"size": 24576
}
}
}
bash
OUT_FILE_ID=$(curl -sS -X POST "$BASE/v1/tools/translate_image/execute" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$IN_FILE_ID\",\"to\":\"$TO\"}" \
| jq -r '.tool_result.data.file_id')
Replace $TO with the target language code (e.g., en, ja, zh-Hans).
Response:
json
{
"code": 200,
"tool": "translate_image",
"tool_result": {
"success": true,
"data": {
"file_id": "file_1741857701_9988aabbccdd",
"target_type": ""
},
"metadata": {
"engine": "imagetranslate"
}
}
}
bash
curl -sS -X POST "$BASE/v1/tools/download_file/execute?response_mode=raw" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$OUT_FILE_ID\"}" \
-o /path/to/translated.png
Critical: The response_mode=raw query parameter is required to get the binary file. Without it, the response is JSON.
bash
BASE="https://ai-tools.camscanner.com"
INPUT_IMAGE="/path/to/image.png"
OUTPUT_FILE="/path/to/translated.png"
TO="en" # target language code — see mapping table above
# Upload
IN_FILE_ID=$(curl -sS -X POST "$BASE/v1/tools/upload_file/execute" \
-H "Content-Type: application/octet-stream" \
--data-binary "@$INPUT_IMAGE" | jq -r '.tool_result.data.file_id')
# Translate
OUT_FILE_ID=$(curl -sS -X POST "$BASE/v1/tools/translate_image/execute" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$IN_FILE_ID\",\"to\":\"$TO\"}" \
| jq -r '.tool_result.data.file_id')
# Download
curl -sS -X POST "$BASE/v1/tools/download_file/execute?response_mode=raw" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$OUT_FILE_ID\"}" \
-o "$OUTPUT_FILE"
If the user requests a language not in the common mapping table, look it up dynamically:
bash
TARGET_LANG="Romanian" # or Chinese name like "罗马尼亚语"
LANG_DATA=$(curl -sS "https://open.camscanner.com/sync/get_languages")
TO=$(echo "$LANG_DATA" | jq -r --arg lang "$TARGET_LANG" \
'.data | to_entries[] | select(.value.name == $lang or .value.chineseName == $lang or .value.nativeName == $lang) | .key')
if [ -z "$TO" ] || [ "$TO" = "null" ]; then
echo "Unsupported language: $TARGET_LANG"; exit 1
fi
MistakeFixForgetting response_mode=raw on downloadAlways append ?response_mode=raw to the download URLWrong Content-Type on uploadUpload uses application/octet-stream, not multipart/form-dataUsing GET instead of POSTAll three endpoints use POSTMissing to parameterAlways include target language code in the translate requestWrong language codeUse codes from the mapping table; for uncommon languages, use the lookup APIUsing "zh" instead of "zh-Hans"Chinese Simplified is zh-Hans, not zh; Traditional is zh-Hant
Check each step before proceeding:
bash
# After upload
if [ -z "$IN_FILE_ID" ] || [ "$IN_FILE_ID" = "null" ]; then
echo "Upload failed"; exit 1
fi
# After translate
if [ -z "$OUT_FILE_ID" ] || [ "$OUT_FILE_ID" = "null" ]; then
echo "Translation failed"; exit 1
fi