Parameter Access and Embedding Integration
PhoText is an AI-powered image text editing tool that focuses on simple and efficient image text modification. It supports multi-platform usage on computers and mobile devices. No professional photo editing skills required - just click on text to edit directly. It also provides additional features like image translation and font recognition to meet various image text processing needs.
Parameters
PhoText supports passing image URLs to open in the editor for editing through the following link format:
https://photext.ai/editor?image_url=${YOUR_IMAGE_URL}(Replace ${YOUR_IMAGE_URL} with the target image's online link)
No public URL for your image? Skip image_url and push the image in as a Blob or base64 instead.
Other Parameters
| Parameter Name | Function | Example |
|---|---|---|
responsive | Controls interface layout. When responsive=true, uses responsive interface (suitable for small screen embedding). Default is three-column large screen layout. | https://photext.ai/editor?image_url=xxx&responsive=true |
hide_header | Hides the editor header on both desktop and mobile. Useful when the host page already provides its own chrome. | https://photext.ai/editor?image_url=xxx&hide_header=true |
disable_ai | Turns off every AI entry point: sidebar AI tab, mobile AI FAB, AI edit after selecting text, the manual/AI switch bar, and AI Removal in both the Removal panel and the text panel's background picker. | https://photext.ai/editor?image_url=xxx&disable_ai=true |
disable_upload | The host supplies the image (image_url or a direct push), so the editor never asks the visitor for a file: no upload prompt on an empty canvas, no "open another image" in the header menu. | https://photext.ai/editor?disable_upload=true |
| Language Parameter | Add language code to the link to set editor interface language, Supports English (en), Simplified Chinese (cn), Traditional Chinese (hant), Japanese (jp), Korean (ko), Thai (th), Russian (ru), Hindi (hi), French (fr), Spanish (es), and Portuguese (pt). | https://photext.ai/en/editor?image_url=xxx (English interface) |
Common embed combination for small screens:
https://photext.ai/en/m/editor?image_url=xxx&responsive=true&hide_header=true&disable_ai=true&disable_upload=trueWhen embedded, the editor no longer asks whether to switch to the desktop / mobile version — the link you pass decides which layout is used.
Embedding
iframe embedding code:
<template #default>
<iframe
:src="iframeSrc"
style="min-width:400px;min-height:600px;border:none;"
/>
</template>Example:
Getting the edited image (postMessage)
The parent page can ask the iframe editor for the current edited image (watermark-free PNG data URL) via postMessage.
Parent → editor
iframe.contentWindow.postMessage(
{ type: 'editor:get-result', requestId: 'optional-id' },
'https://photext.ai', // prefer an explicit target origin; '*' is ok in local dev
)| Field | Type | Description |
|---|---|---|
type | 'editor:get-result' | Required |
requestId | string (optional) | Echoed back so concurrent requests can be matched |
format | 'png' | 'jpeg' | 'webp' (optional) | Defaults to png (lossless). Unknown values fall back to png |
quality | 0–1 (optional) | Only for jpeg / webp; ignored for png |
Editor → parent
Success:
{
type: 'editor:result',
requestId: 'optional-id',
dataUrl: 'data:image/png;base64,...',
mimeType: 'image/png',
width: 1200,
height: 800,
}Failure:
{
type: 'editor:result-error',
requestId: 'optional-id',
error: 'Editor is not ready',
code: 'not_ready', // not_ready | no_image | export_failed
}Branch on code; the error string may change.
Ready notice
The editor broadcasts this once it has loaded:
{ type: 'editor:ready' }It means "the editor can accept commands", not "the canvas already has an image". You don't need to wait for it before asking for the result — editor:get-result waits for the canvas internally.
The broadcast can land before your page attaches its message listener (likely when the first load is slow, or the iframe starts loading early), so don't rely on the broadcast alone. When you do need to know the editor is up — before pushing an image in, say — poll for it, and the editor replies with the same editor:ready right away:
const timer = setInterval(() => {
iframe.contentWindow.postMessage({ type: 'editor:ping' }, 'https://photext.ai')
}, 600)
// clearInterval(timer) once editor:ready arrivesParent example
const iframe = document.querySelector('iframe')
window.addEventListener('message', (event) => {
// In production, verify event.origin
const data = event.data
if (!data || typeof data !== 'object') return
if (data.type === 'editor:result') {
console.log('edited image', data.dataUrl)
// e.g. preview: document.getElementById('preview').src = data.dataUrl
}
if (data.type === 'editor:result-error') {
console.error(data.code, data.error)
}
if (data.type === 'editor:ready') {
// The editor accepts commands now (e.g. push an image in)
}
})
function requestEditedImage() {
iframe.contentWindow.postMessage(
{ type: 'editor:get-result', requestId: String(Date.now()) },
'*',
)
}Notes:
- If you ask before the canvas is ready, the editor waits and then answers; it only returns
not_readyafter a long timeout, so you don't need your own retry loop. - The payload is the current edited full image, not the original upload.
- Exported at the canvas' native pixel size (
width/heightare included).
Pushing an image in (no public URL needed)
image_url requires the image to be reachable on the public internet. If your page already holds a Blob / File / base64 (something you just composed, or downloaded from your own service), send it straight to the editor and let the editor run its own upload flow — that removes the "upload to your storage, then have the editor fetch it back" round trip.
Open the editor without image_url, then post once you receive editor:ready:
iframe.contentWindow.postMessage(
{
type: 'editor:open-image',
requestId: 'optional-id',
blob, // preferred: Blob / File cross windows as-is, no base64 bloat
filename: 'poster.png',
},
'https://photext.ai',
)| Field | Type | Description |
|---|---|---|
type | 'editor:open-image' | Required |
blob | Blob / File | Preferred. Pick one of the three payload forms |
arrayBuffer | ArrayBuffer | Can be zero-copy transferred via postMessage's third argument |
dataUrl | string | data:image/png;base64,...; a bare base64 string also works |
filename | string (optional) | Defaults to embed-image.<ext>; the extension is appended for you |
mimeType | string (optional) | Highest priority. Otherwise inferred from the payload type, then magic bytes |
requestId | string (optional) | Echoed back |
The editor replies with:
{ type: 'editor:open-image-progress', requestId, percentage: 42 } // upload progress 0–100
{ type: 'editor:image-opened', requestId, recordId: 'aBc123' } // open and editable
{ type: 'editor:open-image-error', requestId, error: '...', code: 'bad_payload' }code is either bad_payload (unusable payload) or upload_failed (upload / record creation failed).
The recordId you get back is the same thing as the ?id= parameter: you can reopen the exact same image later with https://photext.ai/editor?id=<recordId> without uploading again.
Switching back to an image you already pushed
Keep the recordId per image on your side and hop between them without a second upload — the editor just switches records, so each one keeps its own edits and the iframe never reloads:
iframe.contentWindow.postMessage(
{ type: 'editor:open-record', requestId: 'optional-id', recordId },
'https://photext.ai',
)The reply is the same editor:image-opened as a push (or editor:open-image-error with code: 'bad_payload' if recordId is missing). Nothing comes back within a second or two? You're talking to a build that predates this message — push the bytes again instead.
Zero-copy transfer of an ArrayBuffer:
iframe.contentWindow.postMessage(
{ type: 'editor:open-image', arrayBuffer, mimeType: 'image/webp' },
'https://photext.ai',
[arrayBuffer], // after transfer your copy is detached
)Notes:
- The editor compresses, uploads, creates the record and switches to the image itself — you don't need to change the iframe
src. - Images only. For PDFs or very long screenshots that need to be split into pages, keep using
image_urlor your own upload page. - The image is downscaled to the editor's size limit exactly like a manual upload.
