jz BytePlus Seedance Fetch (by task id)
Rescue a paid-for video by its task id
- video
- task_id
- applied
- usage
Here's the thing nobody tells you about API video generation: the money leaves your account the instant the job is accepted. A Seedance task can't be cancelled - BytePlus returns 409 if you try to delete a running one. So when your graph blows up after the submit, or your poll times out at 900 seconds on a slow 4K job, the honest first instinct ("just hit queue again") is the one that charges you twice.
This node exists so you don't do that.
What it does
It takes a task id and gives you the finished video back. That's it. Reads on ModelArk are free, and tasks stick around for 48 hours, so a job that outlived its poll timeout isn't money lost - it's a job you pick up later.
task_id is the input that matters: the cgt-… string. If you still have the original graph, wire the task_id output of jz BytePlus Seedance straight into it and the pairing just works. If you don't, the id is printed in the console during the submit ([jz seedance] task <id> - billed from here, cannot be cancelled), and it's also in the task_id output you should have been saving. Paste it in.
wait is the only other real decision. On - the default - it polls until the task settles, exactly like the generate node does. Off, it does a single read and raises if the task isn't finished yet, which is what you want when you're scripting "collect these four jobs overnight" rather than sitting in front of the canvas.
api_key should stay empty; the key resolves server-side from BYTEPLUS_API_KEY in the env or the pack's .env, or [BYTEDANCE] ARK_API_KEY in config.ini. region has to match the region the key was issued in - keys are region-scoped, and a mismatch surfaces as a misleading "key is missing or invalid" 401. poll_timeout (default 900s) and poll_interval (default 3s) only matter when wait is on.
Outputs are the same four the generate node returns: video (native VIDEO, ready for a video sink like core's SaveVideo), task_id, applied (the parameters the server actually used, which is how you catch a silently dropped flag), and usage.
The pattern worth knowing
The generate node hands you task_id for exactly this reason, so the useful shape is submit-once, fetch-later. Two ways people use it:
- Recovery. Something errored downstream - an OOM on a video-save node, a VAE you forgot to load, a crash. Re-run only the fetch node with the id. No second charge.
- Decoupling. Submit a batch of jobs, walk away, then fetch each id at your leisure. Polling happens in whichever run you choose, instead of holding a graph open for fifteen minutes.
Install
Same pack, so nothing extra if you already have it. Otherwise, ComfyUI Manager → search comfyui-jz, or:
cd ComfyUI/custom_nodes
git clone https://github.com/j-zhang19/comfyui-jz
Restart ComfyUI, then drop your key into ComfyUI/custom_nodes/comfyui-jz/.env:
BYTEPLUS_API_KEY=your-key-here
No model downloads, no heavy dependencies - the pack needs only requests, pillow and numpy.
If it isn't working
wait off and the task still running is a raise, not a hang - that's the design, and the message says to turn wait on. A read that errors out usually means the id is stale: 48 hours is the real ceiling, and there's no way to recover a task after that window closes. Wrong region gives the region-scoped 401 described above rather than a "not found", which is worth remembering because it sends you debugging the id instead of the region widget.
One thing this node can't do: cancel. Nothing can. If you submitted it, it's bought.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| task_id | STRING | cgt-… from the generate node; tasks live 48h | |
| wait | BOOLEAN | true | on: poll until it finishes. off: raise if it is not done yet |
| api_keyopt | STRING | — | |
| regionopt | COMBO | ap-southeast | 2 options: ap-southeast, eu-west |
| poll_timeoutopt | INT | 90030–7200 | — |
| poll_intervalopt | INT | 31–30 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | — |
| task_id | STRING | — |
| applied | STRING | — |
| usage | STRING | — |