Scripts personalizados
Os scripts integrados cobrem os fluxos comuns. Quando você precisa de algo que eles não fazem — uma etapa em outra ordem, uma tela que eles nunca tocam ou um app que não é TikTok nem Instagram — você pode escrever por conta própria em qualquer linguagem e deixar o TikMatrix entregar o telefone para você.
Requisitos
Scripts personalizados exigem um plano Pro, Team ou Business. O plano Starter não tem acesso.
O número de dispositivos do seu plano também é o limite de concorrência: um plano Pro (20 dispositivos) pode controlar 20 telefones ao mesmo tempo, seja por tarefas integradas, scripts personalizados ou uma mistura dos dois.
Duas formas de rodar um script
Autônoma
Você mesmo executa o programa. O TikMatrix apenas empresta os dispositivos.
from tikmatrix import TikMatrix
client = TikMatrix()
for device in client.devices():
if device["busy"]:
continue
with client.device(device["serial"], label="my crawler") as d:
d.press("home")
print(d.info())
Boa para trabalhos pontuais, coleta de dados e qualquer coisa que você queira rodar pelo seu próprio agendador.
Gerenciada
Você registra o programa no TikMatrix e ele vira uma tarefa como qualquer outra. Ganha a fila de tarefas, a concorrência por plano, as novas tentativas automáticas, o log de tarefas e os modelos de agendamento. O TikMatrix aluga o dispositivo antes de iniciar seu programa e passa o id do aluguel no ambiente.
from tikmatrix import TikMatrix
with TikMatrix.from_env() as d: # dispositivo já alugado
d.click(text="Log in")
print("done") # esta linha vai parar no log da tarefa
Boa para tudo que você quer rodar repetidamente, em horário marcado ou em muitos dispositivos.
Qual escolher
| Autônoma | Gerenciada | |
|---|---|---|
| Quem inicia | Você | A fila de tarefas do TikMatrix |
| Aluguel do dispositivo | Você adquire | Já está em mãos ao iniciar |
| Novas tentativas, agendamento, log | Você constrói | Já vem incluído |
| Rodar em muitos dispositivos | Você escreve o laço | Uma tarefa por dispositivo, em paralelo |
| Melhor para | Exploração, crawlers, trabalhos pontuais | Tudo que você quer repetir |
Você pode começar no modo autônomo enquanto acerta o fluxo e depois registrar o mesmo arquivo como script gerenciado — a única linha que muda é TikMatrix.from_env().
Primeiros passos
1. Instale a biblioteca cliente
pip install requests
Depois copie o tikmatrix.py do diretório do SDK para junto do seu script. A biblioteca é um único arquivo, sem outras dependências.
Você não é obrigado a usá-la — a API é JSON puro sobre HTTP, e os endpoints crus estão documentados abaixo.
2. Escreva seu script
from tikmatrix import TikMatrix
client = TikMatrix()
with client.device("192.168.1.5:5555") as d:
d.press("home")
d.adb("shell", "am", "start", "-a", "android.settings.SETTINGS")
d.wait_for(text="Settings", timeout=15)
d.screenshot("settings.png")
Rode com o TikMatrix aberto e o telefone conectado. Se imprimir um dicionário com as informações do dispositivo, está tudo ligado.
3. Registre-o (apenas modo gerenciado)
Vá em Dispositivos → Scripts personalizados → Adicionar script:
| Campo | Significado |
|---|---|
| Nome | Aparece na lista de scripts e no log de tarefas |
| Comando | A linha do programa a executar, ex.: python C:/scripts/my_flow.py |
| Diretório de trabalho | Opcional. Onde o programa inicia |
| Plataforma | Veja modos de plataforma abaixo |
| Tempo limite | Segundos até o script ser encerrado e a tarefa marcada como falha. Padrão 1800 |
| Variáveis de ambiente extras | Objeto JSON opcional mesclado ao ambiente do programa |
| Habilitado | Desliga um script sem apagá-lo. Um script desabilitado não pode ser despachado |
Depois clique em ▶ na linha do script e escolha os dispositivos, exatamente como em um script integrado.
O Assistente de IA pode redigir um script personalizado a partir de uma descrição em linguagem comum e registrá-lo em uma única etapa. Ele mostra o arquivo inteiro antes de gravar qualquer coisa em disco.
Aluguéis de dispositivo
Um telefone só pode ser controlado por uma coisa de cada vez. Alugá-lo avisa ao TikMatrix que o dispositivo está ocupado, de modo que:
- a fila de tarefas não despacha uma tarefa para a mesma tela, e
- suas chamadas JSON-RPC reportam a saúde do agente exatamente como um script integrado faz, então o watchdog vê um agente ocupado em vez de um agente mudo.
Um aluguel também consome uma vaga de dispositivo do seu plano.
Aluguéis expiram — 120 segundos por padrão, 600 no máximo. A biblioteca Python renova o seu em uma thread de fundo e o libera quando o bloco with termina, então um script que quebra libera o dispositivo em segundos em vez de segurá-lo até você reiniciar o app. Se você chamar a API diretamente, precisa enviar os heartbeats por conta própria.
Você vê todos os aluguéis ativos — e pode liberar um à força — em Configurações → Developer API → Sessões de dispositivo ativas.
Modos de plataforma
Um script registrado declara o alvo:
Generic — o dispositivo é entregue intocado. Nenhum app é aberto, nenhuma troca de conta, nenhuma verificação de método de entrada e nada é fechado depois. Use para automatizar qualquer coisa que não seja TikTok ou Instagram.
TikTok / Instagram — o app é aberto e a conta trocada antes do seu programa começar, e o app é fechado ao terminar, exatamente como em um script integrado. TIKMATRIX_PACKAGE informa qual pacote foi resolvido. Use para acrescentar uma etapa que os scripts integrados não cobrem.
Variáveis de ambiente
Um script gerenciado recebe:
| Variável | Significado |
|---|---|
TIKMATRIX_API_BASE | URL do servidor, ex.: http://127.0.0.1:50809 |
TIKMATRIX_SESSION_ID | O aluguel já mantido em seu nome |
TIKMATRIX_SERIAL | O dispositivo para o qual esta tarefa foi despachada |
TIKMATRIX_PACKAGE | Pacote do app resolvido |
TIKMATRIX_PLATFORM | tiktok, instagram ou generic |
TikMatrix.from_env() lê tudo isso por você.
Scripts autônomos não recebem nada disso — alugue um dispositivo explicitamente.
Tudo o que você colocar em Variáveis de ambiente extras é mesclado por cima, que é a forma usual de dar a um mesmo script registrado configurações por execução sem editar o arquivo.
Referência da biblioteca Python
TikMatrix — a conexão
| Chamada | O que faz |
|---|---|
TikMatrix(base_url=None, timeout=30.0) | Conecta. Recorre a TIKMATRIX_API_BASE e depois a http://127.0.0.1:50809 |
client.devices() | Dispositivos on-line, cada um com serial, real_serial e busy |
client.sessions() | Todos os aluguéis ativos, inclusive os de outros processos |
client.device(serial, label=..., ttl_secs=120) | Aluga um dispositivo e devolve um Device |
TikMatrix.from_env() | Adota o dispositivo com que um script gerenciado foi iniciado |
Device — o telefone
| Chamada | O que faz |
|---|---|
d.info() | Informações do dispositivo pelo UIAutomator2 |
d.window_size() | (largura, altura) |
d.screenshot(path=None) | Bytes PNG, opcionalmente gravados em path |
d.hierarchy() | A árvore de UI atual em XML |
d.find(text=, resource_id=, description=, class_name=) | Nós correspondentes, cada um com bounds e center |
d.exists(**criteria) | Se há alguma correspondência |
d.wait_for(timeout=10.0, interval=1.0, **criteria) | Bloqueia até aparecer e devolve o elemento |
d.click(timeout=10.0, **criteria) | Espera o elemento e toca no centro dele |
d.click_xy(x, y) | Toca em uma coordenada |
d.swipe(sx, sy, ex, ey, steps=20) | Desliza |
d.press(key) | back, home, recent, enter, … |
d.input_text(text) | Digita no campo em foco pelo IME rápido incluído |
d.jsonrpc(method, params=None, timeout=10) | Qualquer método do UIAutomator2 |
d.adb(*args, timeout_ms=None) | Executa um comando ADB |
d.release() | Libera o aluguel. O with faz isso por você |
O find casa contra a árvore de UI despejada, então quando um seletor erra você pode fazer print(d.hierarchy()) e ver exatamente o que foi pesquisado. O Inspetor de elementos na visão do dispositivo mostra a mesma árvore visualmente, o que costuma ser o jeito mais rápido de achar um resource-id.
input_text precisa de ADBEle envia um broadcast ao método de entrada incluído, o que passa por adb shell. Habilite o acesso ADB antes de usar, ou ele falha com 403.
Erros
A biblioteca levanta duas exceções, ambas subclasses de RuntimeError:
| Exceção | Quando |
|---|---|
DeviceBusyError | HTTP 409 — o dispositivo já está alugado, ou o plano não tem vaga livre |
TikMatrixError | Todo o resto: plano insuficiente, aluguel expirado, ADB desabilitado, seletor que nunca casou |
from tikmatrix import TikMatrix, TikMatrixError, DeviceBusyError
client = TikMatrix()
try:
with client.device("192.168.1.5:5555") as d:
d.click(text="Log in", timeout=20)
except DeviceBusyError:
print("esse telefone está com outro processo — tente outro")
except TikMatrixError as exc:
print("falhou:", exc)
Em um script gerenciado, deixar a exceção escapar costuma ser o certo: a saída diferente de zero marca a tarefa como falha e o traceback vai para o log da tarefa.
Endpoints HTTP
Operações de dispositivo precisam de um cabeçalho x-session-id nomeando um aluguel ativo. Não há chave de API: como o resto da API local, esses endpoints não são autenticados — conseguir alcançar a máquina na rede é o controle de acesso. Eles não enviam cabeçalhos CORS, então chame-os a partir de um programa (curl, Python, qualquer código de servidor) e não de uma página no navegador.
| Método | Caminho | Finalidade |
|---|---|---|
GET | /api/v1/rpc/devices | Lista dispositivos on-line e se cada um está ocupado |
POST | /api/v1/rpc/session | Aluga um dispositivo → session_id |
POST | /api/v1/rpc/session/{id}/heartbeat | Estende o aluguel |
DELETE | /api/v1/rpc/session/{id} | Libera o aluguel |
GET | /api/v1/rpc/session | Lista os aluguéis ativos |
POST | /api/v1/rpc/jsonrpc | Chama um método do UIAutomator2 |
POST | /api/v1/rpc/adb | Executa um comando ADB |
GET | /api/v1/rpc/hierarchy?serial= | Árvore de UI atual em XML |
GET | /api/v1/rpc/screenshot?serial= | Tela atual em PNG |
As respostas JSON usam o mesmo envelope do resto da API local — {"code": 0, "message": "success", "data": ...}, com code diferente de zero em caso de falha. hierarchy e screenshot devolvem o corpo cru.
Exemplo
# Alugar um dispositivo
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","label":"curl test","ttl_secs":120}'
# {"code":0,"message":"success","data":{"session_id":"ff3ae079-...","serial":"192.168.1.5:5555", ...}}
# Controlá-lo
curl -X POST http://127.0.0.1:50809/api/v1/rpc/jsonrpc \
-H "x-session-id: ff3ae079-..." \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","method":"deviceInfo","params":[]}'
# Manter vivo enquanto trabalha
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-.../heartbeat \
-H "Content-Type: application/json" \
-d '{"ttl_secs":120}'
# Devolvê-lo
curl -X DELETE http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-...
Erros
| Status | Significado |
|---|---|
| 403 | Plano abaixo de Pro, sem aluguel, aluguel expirado ou acesso ADB desabilitado |
| 409 | Dispositivo já alugado, ou o plano não tem vaga livre |
Escrever em outra linguagem
Nada aqui é específico de Python. Qualquer runtime capaz de fazer uma requisição HTTP serve — o contrato do modo gerenciado é só "leia três variáveis de ambiente e saia com 0 em caso de sucesso".
// my_flow.js — registre com: node C:/scripts/my_flow.js
const base = process.env.TIKMATRIX_API_BASE || "http://127.0.0.1:50809";
const serial = process.env.TIKMATRIX_SERIAL;
const session = process.env.TIKMATRIX_SESSION_ID;
async function jsonrpc(method, params = []) {
const res = await fetch(`${base}/api/v1/rpc/jsonrpc`, {
method: "POST",
headers: { "content-type": "application/json", "x-session-id": session },
body: JSON.stringify({ serial, method, params }),
});
const body = await res.json();
if (!res.ok || body.code !== 0) throw new Error(body.message || res.statusText);
return body.data;
}
console.log(await jsonrpc("deviceInfo"));
Se o interpretador não estiver no PATH, informe o caminho completo em Comando, ex.: C:/Program Files/nodejs/node.exe C:/scripts/my_flow.js.
Disparar um script personalizado pela API
Scripts registrados também podem ser iniciados pela API de gerenciamento de tarefas, de modo que um script pode enfileirar trabalho subsequente:
curl -X POST http://127.0.0.1:50809/api/v1/task \
-H "Content-Type: application/json" \
-d '{
"serials": ["192.168.1.5:5555"],
"script_name": "custom_script",
"script_config": {
"custom_script_id": 1,
"custom_script_platform": "generic"
}
}'
custom_script_id é o id do script que você registrou.
Acesso ADB
/api/v1/rpc/adb dá aos seus scripts um shell no dispositivo — você precisa dele para enviar mídia, instalar APKs e mudar configurações do sistema. Como é um shell completo em um endpoint sem chave de API, ele vem desligado. Ligue em Configurações → Developer API → Permitir comandos ADB quando tiver um script que precise dele; a automação de UI por /rpc/jsonrpc funciona sem ele.
Enquanto está desligado, /api/v1/rpc/adb responde 403 e o resto da API continua funcionando. Todo comando ADB que um script executa é gravado no seu arquivo de log.
Como escrever scripts que continuam funcionando
- Espere a tela, não durma por ela.
d.wait_for(...)retorna assim que o elemento aparece; um sleep fixo é ou mais lento do que precisa ou curto demais num dia ruim. - Verifique antes de tocar. Um
d.exists(...)num diálogo de consentimento ou num aviso de "agora não" custa um despejo da árvore e salva uma execução que, sem ele, tocaria no vazio. - Imprima o que você fez. No modo gerenciado, o stdout é o log da tarefa, e é o único registro de uma execução que ninguém acompanhou.
- Torne a reexecução segura. Uma nova tentativa roda o programa inteiro de novo, então um script que publica deve checar se já publicou em vez de supor que começa do zero.
- Um script, um trabalho. A concorrência é por dispositivo, então dez tarefas pequenas em dez telefones terminam muito antes do que um script percorrendo dez telefones em laço.
Notas e limites
- O comando é executado diretamente, não por um shell, então
&&e|são tratados como argumentos e não como operadores. Registrecmd /c "..."(Windows) oush -c "..."(macOS) se quiser comportamento de shell. - Coloque entre aspas caminhos com espaços:
"C:/Program Files/Python/python.exe" my_script.py. - Um script que ultrapassa o tempo limite é encerrado e a tarefa é marcada como falha.
- Um código de saída diferente de zero marca a tarefa como falha; tudo que o script escreve em stdout e stderr vai para o log da tarefa.
- Scripts rodam com as mesmas permissões do próprio TikMatrix. Registre apenas programas que você escreveu ou em que confia.
Solução de problemas
API access requires Pro or higher plan (403)
A licença nesta máquina é Starter ou está inativa. Verifique Configurações → Licença.
Conexão recusada em 127.0.0.1:50809
O TikMatrix não está rodando, ou está rodando como outro usuário. O servidor só existe enquanto o app está aberto.
409 em toda tentativa de aluguel Ou o telefone está de fato ocupado — veja em Configurações → Developer API → Sessões de dispositivo ativas — ou todas as vagas de dispositivo do plano já estão tomadas por tarefas em execução.
O aluguel expira no meio de uma etapa longa
O TTL padrão é 120 s e a biblioteca renova em segundo plano, então isso normalmente significa que o script bloqueou a thread principal por mais tempo que o TTL. Aumente ttl_secs (até 600) ou tire o trabalho longo dessa thread.
d.adb(...) falha com 403
O acesso ADB está desligado. Ligue em Configurações → Developer API → Permitir comandos ADB.
Um seletor nunca casa
print(d.hierarchy()) mostra exatamente a árvore que o find pesquisou. O texto é comparado de forma exata, então um espaço a mais ou um rótulo traduzido é a causa mais comum; casar por resource_id é mais estável do que por text.
A tarefa é marcada como falha mas o telefone parece bem Leia o log da tarefa. Uma saída diferente de zero — inclusive uma exceção não tratada ao fim de uma execução bem-sucedida — reprova a tarefa mesmo que a automação em si tenha funcionado.
Próximos passos
- Visão geral da API local — autenticação e formato de resposta
- API de gerenciamento de tarefas — criar, consultar, repetir e parar tarefas
- Assistente de IA — deixe um modelo redigir e registrar um script por você
- SDK e exemplos no GitHub