Use CamScanner to erase handwriting from images while preserving the printed content and original layout. Powered by a high-precision image enhancement engin...
---
name: camscanner-image-erase-handwriting
description: Use CamScanner to erase handwriting from images while preserving the printed content and original layout. Powered by a high-precision image enhancement engine that intelligently detects and removes handwritten strokes, annotations, and signatures, leaving the underlying document clean and legible. Use when the user wants to remove handwriting from a photo or scan, clean up annotated documents, or restore a blank form filled by hand. Triggers on "erase handwriting", "remove handwriting from image", "clean handwritten notes", "remove annotations from scan", or when the user has an image with handwritten content that needs to be removed.
metadata:
author: CamScanner
version: "1.0"
openclaw:
emoji: "✍️"
requires:
bins: ["curl", "jq"]
homepage: "https://www.camscanner.com"
---
# CamScanner Image Erase Handwriting
## Overview
CamScanner provides a high-precision image enhancement engine that removes handwriting from images while preserving the printed content and original layout. It intelligently detects handwritten strokes, annotations, and signatures and erases them, leaving the underlying document clean and legible. The workflow is a 3-step pipeline: **upload** the image, **enhance** it with `enhance_mode: 9` (erase handwriting), then **download** the result. For convenience, the enhance step also supports a `raw` output mode that returns the processed image bytes directly, skipping the download step.
## When to Use
- User wants to remove handwriting, annotations, or signatures from an image
- User has a scan or photo of a document with handwritten notes that need to be cleaned
- User wants to restore a blank form after it was filled in by hand
- User has an annotated scan and needs a clean copy for OCR, printing, or sharing
## Privacy & Data
> **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.
## API Reference
**Base URL:** `https://ai-tools.camscanner.com`
### Supported Enhancements
| source_type | enhance_mode | Operation | Output |
| ----------- | ------------ | ------------------ | ------ |
| image | 9 | Erase handwriting | .jpg |
### Step 1: Upload Image
```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.jpg" | 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
}
}
}
```
### Step 2: Enhance Image (Erase Handwriting)
```bash
OUT_FILE_ID=$(curl -sS -X POST "$BASE/v1/tools/enhance_image/execute" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$IN_FILE_ID\",\"enhance_mode\":9,\"output_mode\":\"file_id\"}" \
| jq -r '.tool_result.data.file_id')
```
**Response:**
```json
{
"code": 200,
"tool": "enhance_image",
"tool_result": {
"success": true,
"data": {
"file_id": "file_1741857701_9988aabbccdd",
"enhance_mode": 9
}
}
}
```
### Step 3: Download Result
```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/output.jpg
```
**Critical:** The `response_mode=raw` query parameter is required to get the binary file. Without it, the response is JSON.
### Alternative: One-Shot Raw Output
If you don't need a reusable `file_id` for the result, pass `"output_mode": "raw"` to `enhance_image` and save the response body directly — this combines steps 2 and 3:
```bash
curl -sS -X POST "$BASE/v1/tools/enhance_image/execute" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$IN_FILE_ID\",\"enhance_mode\":9,\"output_mode\":\"raw\"}" \
-o /path/to/output.jpg
```
## Quick Reference: Complete Pipeline
Erase handwriting from an image (three-step, keeps an output `file_id`):
```bash
BASE="https://ai-tools.camscanner.com"
INPUT_IMAGE="/path/to/image.jpg"
OUTPUT_FILE="/path/to/output.jpg"
# 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')
# Enhance (erase handwriting)
OUT_FILE_ID=$(curl -sS -X POST "$BASE/v1/tools/enhance_image/execute" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$IN_FILE_ID\",\"enhance_mode\":9,\"output_mode\":\"file_id\"}" \
| 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"
```
Or one-shot (two-step, raw image stream straight from `enhance_image`):
```bash
BASE="https://ai-tools.camscanner.com"
INPUT_IMAGE="/path/to/image.jpg"
OUTPUT_FILE="/path/to/output.jpg"
# 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')
# Enhance + download in one call
curl -sS -X POST "$BASE/v1/tools/enhance_image/execute" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$IN_FILE_ID\",\"enhance_mode\":9,\"output_mode\":\"raw\"}" \
-o "$OUTPUT_FILE"
```
## Common Mistakes
| Mistake | Fix |
| --------------------------------------------------- | ----------------------------------------------------------------------------- |
| Forgetting `response_mode=raw` on download | Always append `?response_mode=raw` to the download URL |
| Wrong Content-Type on upload | Upload uses `application/octet-stream`, not `multipart/form-data` |
| Using GET instead of POST | All endpoints use POST |
| Passing `enhance_mode` as a string | `enhance_mode` is an integer — use `9`, not `"9"` |
| Missing `output_mode` in enhance request | Must be either `"file_id"` (then download separately) or `"raw"` (stream out) |
| Parsing JSON when `output_mode` is `"raw"` | With `raw`, the response body IS the image — write it to a file with `-o` |
| Trying to download a `file_id` after `raw` response | `raw` mode returns no `file_id`; re-run in `file_id` mode if you need one |
## Error Handling
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 enhance (file_id mode)
if [ -z "$OUT_FILE_ID" ] || [ "$OUT_FILE_ID" = "null" ]; then
echo "Enhancement failed"; exit 1
fi
```
don't have the plugin yet? install it then click "run inline in claude" again.
added explicit intent section, documented network/dependency inputs, split procedure into numbered steps with inputs/outputs, added decision points for output_mode choice and error handling, specified output contract with file format and success criteria, and added outcome signal for user verification.
remove handwriting, annotations, and signatures from images while keeping printed text and document layout intact. use this when you need to clean up scanned documents, restore blank forms after they've been filled in by hand, or prepare annotated images for ocr or sharing. the skill sends your image to camscanner's servers, processes it with a high-precision enhancement engine set to erase-handwriting mode, and returns a clean copy to your local filesystem.
required parameters:
INPUT_IMAGE (file path): local path to the jpg or png image containing handwriting to remove. file must exist and be readable.OUTPUT_FILE (file path): where to save the cleaned image. directory must be writable. output is always jpg.external dependencies:
curl: http client for making api calls. required.jq: json parser for extracting file ids from responses. required.network:
https://ai-tools.camscanner.com. no authentication required (no api key).privacy note: your image is uploaded to camscanner's servers for processing. files are processed in real-time and not permanently retained. output files are saved only to your local filesystem.
step 1: upload image to camscanner
input: $INPUT_IMAGE (local file path)
run:
curl -sS -X POST "https://ai-tools.camscanner.com/v1/tools/upload_file/execute" \
-H "Content-Type: application/octet-stream" \
--data-binary "@$INPUT_IMAGE" | jq -r '.tool_result.data.file_id'
output: $IN_FILE_ID (string, e.g. file_1741857600_ab12cd34ef56)
step 2: enhance image with erase-handwriting mode
input: $IN_FILE_ID (from step 1)
choose one sub-step based on whether you need to reuse the output file id:
step 2a (if you want to keep the output file id for later download):
run:
curl -sS -X POST "https://ai-tools.camscanner.com/v1/tools/enhance_image/execute" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$IN_FILE_ID\",\"enhance_mode\":9,\"output_mode\":\"file_id\"}" | jq -r '.tool_result.data.file_id'
output: $OUT_FILE_ID (string, e.g. file_1741857701_9988aabbccdd). proceed to step 3.
step 2b (if you want the cleaned image streamed directly to disk, skipping step 3):
run:
curl -sS -X POST "https://ai-tools.camscanner.com/v1/tools/enhance_image/execute" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$IN_FILE_ID\",\"enhance_mode\":9,\"output_mode\":\"raw\"}" \
-o "$OUTPUT_FILE"
output: jpg image written directly to $OUTPUT_FILE. skip step 3; you are done.
step 3: download cleaned image (only if you used step 2a)
input: $OUT_FILE_ID (from step 2a)
run:
curl -sS -X POST "https://ai-tools.camscanner.com/v1/tools/download_file/execute?response_mode=raw" \
-H "Content-Type: application/json" \
-d "{\"file_id\":\"$OUT_FILE_ID\"}" \
-o "$OUTPUT_FILE"
output: jpg image written to $OUTPUT_FILE
if you want to reuse the output file id later (e.g. download again, pass to another tool):
use step 2a (output_mode: file_id), then step 3. this gives you $OUT_FILE_ID and saves the file locally.
if you want the fastest path and don't need the file id:
use step 2b (output_mode: raw). the image is piped directly from enhance to disk. no step 3. you save one network round trip but cannot retrieve $OUT_FILE_ID later.
if the input image is corrupt or unreadable:
step 1 (upload) will fail silently or return an invalid file id. step 2 will return an error or empty file. validate that $IN_FILE_ID is not null or "null" before proceeding to step 2.
if the network times out during upload or enhance: retry the failing step. upload is idempotent (same image = same file_id, so re-uploading is safe). enhance with output_mode: file_id is also safe to retry (same input produces same output file_id).
if the downloaded file is empty or corrupt: the enhance step may have failed silently. check that enhance returned a non-null file_id. if file_id is valid but output is empty, re-run the enhance step.
success case:
$OUTPUT_FILEresponse format (intermediate steps):
{"code": 200, "tool": "<tool_name>", "tool_result": {"success": true, "data": {"file_id": "...", ...}}}file metadata:
$OUTPUT_FILE in an image viewer or editor and see that handwritten marks, annotations, and signatures have been removed