AZ
Ten years of iOS privacy protection plugins
AZ TUTORIALS · API reference

CTW Pro · API reference

CTW Pro offers both HTTP and OpenURL interfaces; the two map one-to-one.

AZ tutorialsRead on siteUpdated 2026-11-01
ItemValue
HTTP base URLhttp://127.0.0.1:8080
OpenURL prefixCTW://?cmd=
MethodGET
Result file/var/mobile/ctwresult.txt
Parameter file/var/mobile/ctwparams.txt

Return values

HTTP response

HTTP endpoints return JSON directly, for example:

json
{"version":"1.0.1","code":0}

code of 0 means the request succeeded; anything else is an error.

Result file

Long-running operations such as a reset or a record switch require polling /var/mobile/ctwresult.txt for the final outcome:

ValueMeaning
0Finished
1Error
2Running — keep waiting
4Reached the last record (nextrecord only)

Note that in the result file 0 means success.

Endpoint list

FunctionHTTP pathOpenURL
Get the version number/version—
Launch the app—CTW://?cmd=open
Reset/newrecordCTW://?cmd=newrecord
Next record/nextrecordCTW://?cmd=nextrecord
Clear every record/deleteallrecordsCTW://?cmd=deleteallrecords
Activate a specific record/activerecord?ID=CTW://?cmd=activerecord&ID=
Activate the first / last record/activefirstrecord · /activelastrecordSame cmd names
Delete a specific record/deleterecord?ID=CTW://?cmd=deleterecord&ID=
Import a record directly/importdirectCTW://?cmd=importdirect
Export a specific record/exportrecord?ID=CTW://?cmd=exportrecord&ID=
Export every record/exportallrecordsCTW://?cmd=exportallrecords
Rename the current record/renamecurrentrecord?name=CTW://?cmd=renamecurrentrecord&name=
Look up an ID from a record name/getbakidfromname?name=CTW://?cmd=getbakidfromname&name=
Get the current record's parameters/getcurrentrecordparamCTW://?cmd=getcurrentrecordparam
Set the current record's parameters/setcurrentrecordparamCTW://?cmd=setcurrentrecordparam
Enable / disable an app/enablerecordapp?bid=&enable=CTW://?cmd=enablerecordapp
Get every record name/getallrecordsnameCTW://?cmd=getallrecordsname
Change the GPS location/relocationwithbid?x=&y=&z=&r=&bid=CTW://?cmd=relocationwithbid

Endpoint details

Get the version number

GET http://127.0.0.1:8080/version

Returns the client version, for example {"version":"1.0.1","code":0}. Useful for checking that CTW is running and the API is reachable.

Launch the app

lua
openURL("CTW://?cmd=open")

OpenURL only. Brings CTW Pro to the foreground.

Reset

GET http://127.0.0.1:8080/newrecord

Generates a new device from the current settings and creates a record. Make sure the target apps are ticked inside the app before calling. Poll the result file afterwards — 0 means finished.

Next record

GET http://127.0.0.1:8080/nextrecord

Switches to the next record in the list. When you are already on the last one, the result file returns 4, which is handy for detecting the end of a rotation cycle.

Clear every record

GET http://127.0.0.1:8080/deleteallrecords

Wipes every backup record. This cannot be undone.

Activate a specific record

GET http://127.0.0.1:8080/activerecord?ID=XXX
ParameterRequiredNotes
IDYesRecord ID. If you only know the record name, get the ID first with Look up an ID from a record name

Activate the first / last record

GET http://127.0.0.1:8080/activefirstrecord
GET http://127.0.0.1:8080/activelastrecord

Activates the first or the last record in the list directly. No parameters needed.

Delete a specific record

GET http://127.0.0.1:8080/deleterecord?ID=XXX
ParameterRequiredNotes
IDYesID of the record to delete

Import a record directly

GET http://127.0.0.1:8080/importdirect

Imports records from /var/mobile/Media/CTWImport/. Zorro backups also go in that folder.

Export a specific record

GET http://127.0.0.1:8080/exportrecord?ID=XXX
ParameterRequiredNotes
IDYesID of the record to export

Exports to /var/mobile/Media/CTWExport/.

Export every record

GET http://127.0.0.1:8080/exportallrecords

Exports all records to /var/mobile/Media/CTWExport/.

Rename the current record

GET http://127.0.0.1:8080/renamecurrentrecord?name=XXX
ParameterRequiredNotes
nameYesNew name. Non-ASCII characters must be URL-encoded — see urlEncode in the Lua example below

Look up an ID from a record name

GET http://127.0.0.1:8080/getbakidfromname?name=XXX
ParameterRequiredNotes
nameYesRecord name. URL-encode it if it contains non-ASCII characters

Finds the backup ID for a record name. Commonly used together with activerecord, deleterecord and exportrecord.

Get the current record's parameters

GET http://127.0.0.1:8080/getcurrentrecordparam

Writes the current record's device parameters to /var/mobile/ctwparams.txt. See Parameter file for the format.

Set the current record's parameters

GET http://127.0.0.1:8080/setcurrentrecordparam

Deprecated

No longer supported after 1.5.2. Do not use this endpoint on newer builds.

Enable / disable an app

GET http://127.0.0.1:8080/enablerecordapp?bid=BUNDLE&enable=1
ParameterRequiredNotes
bidYesBundle ID of the target app
enableYes1 enables, 0 disables

Get every record name

GET http://127.0.0.1:8080/getallrecordsname

Returns JSON directly:

json
{
  "code": 0,
  "data": {
    "records": [
      { "id": "...", "name": "...", "selected": true }
    ],
    "count": 1
  }
}
FieldNotes
records[].idRecord ID
records[].nameRecord name
records[].selectedWhether this is the active record
countTotal number of records

Change the GPS location

GET http://127.0.0.1:8080/relocationwithbid?x=&y=&z=&r=&bid=
ParameterRequiredNotes
xYesLongitude
yYesLatitude
z—Altitude
r—Random offset range
bidYesBundle ID of the target app

Parameter file

Path: /var/mobile/ctwparams.txt

  • One parameter per line, separated by chr(10)
  • The name and value are separated by a colon :
  • Call getcurrentrecordparam and open the file to see the exact format
ParameterNotes
RecordIDRecord ID, e.g. wechat001
RecordNameRecord name, auto-generated by default
DeviceNameDevice name, e.g. xxxx iPhone
SystemVersioniOS version number, e.g. 10.3.1
IDFAIDFA
IDFVIDFV
UDIDDevice UDID
IMEIDevice IMEI
SerialNumDevice serial number
MACMAC address
SSIDWi-Fi network name
BSSIDWi-Fi BSSID

Lua example (TouchSprite)

lua
require "TSLib"
local sz = require("sz")
local http = require("szocket.http")

-- URL encoding (required for non-ASCII record names)
function urlEncode(s)
    s = string.gsub(s, "([^%w%.%- ])", function(c)
        return string.format("%%%02X", string.byte(c))
    end)
    return string.gsub(s, " ", "+")
end

-- Poll the result file: true = done / false = error / "last" = reached the final record
function Check_CTW_Result()
    ::wait::
    mSleep(2000)
    local f = "/var/mobile/ctwresult.txt"
    if isFileExist(f) then
        local r = readFileString(f)
        if r == "0" then return true end
        if r == "1" then return false end
        if r == "2" then
            toast("in progress", 1)
            goto wait
        end
        if r == "4" then return "last" end
    end
end

-- unified call entry point
function CTW(path)
    local res, code = http.request("http://127.0.0.1:8080" .. path)
    if code == 200 then
        return Check_CTW_Result()
    end
    return false
end

-- Reset
CTW("/newrecord")

-- Switch records by name
local res = http.request("http://127.0.0.1:8080/getbakidfromname?name=" .. urlEncode("wechat001"))
-- After pulling the ID out of res:
CTW("/activerecord?ID=XXX")

-- Rename the current record
CTW("/renamecurrentrecord?name=" .. urlEncode("wechat001"))

-- Walk every record
CTW("/activefirstrecord")
while true do
    -- ... your own logic here ...
    if CTW("/nextrecord") == "last" then break end
end

-- OpenURL form
openURL("CTW://?cmd=open")
openURL("CTW://?cmd=newrecord")

For usage, see the CTW Pro user guide.

Note

The interface and supported systems may change with updates. Back up important data before cleaning, resetting or deleting anything.