Reference · Tools
FTP
Transfer files to and from remote servers via FTP or SFTP protocols.
The FTP node connects your workflows to remote FTP or SFTP servers to download, upload, list, delete, and rename files. Use it to automate things like pulling nightly report exports from a vendor SFTP drop, or pushing processed files to a client's FTP server. Both password and private-key authentication are supported.
- Node type
- Action (binary)
- Parameters
- 19
- Outputs
- Output, Error
- Credentials
- FTP / SFTP
FTP
Transfer files via FTP or SFTP
Overview
The FTP tool transfers files between workflow items and remote FTP/SFTP servers. It supports five operations: download (fetch file from remote server into binary data), upload (send binary data or text content to remote server), list (enumerate directory contents with optional recursion), delete (remove files or folders), and rename/move (relocate files or folders). Supports both FTP and SFTP protocols with password or private key authentication.
Category: Development
Tool Name: ftp
Version: 1
Appearance: Icon: lucide-FolderSync | Color: #303050
Node Type
Action (Binary) — handles file/binary data operations
Input / Output
| Direction | Port(s) |
|---|---|
| Input | Input |
| Output | Output, Error |
Credentials
This tool requires FTP / SFTP credentials. See the Credentials Guide for setup instructions.
Operations
| Operation | Value | Description |
|---|---|---|
| Delete | delete | Delete a file or folder |
| Download | download | Download a file |
| List | list | List folder content |
| Rename | rename | Rename/move a file or folder |
| Upload | upload | Upload a file |
Parameters
Delete (delete)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| Path | string | Yes | — | The file path of the file to delete. Has to contain the full path. Supports expressions like {{ $json.path }}. |
| Options | collection | No | {} | Additional options for the delete operation. |
| — Folder | boolean | No | false | Whether folders can be deleted. |
| — Recursive | boolean | No | false | Whether to remove all files and directories in target directory. (shown when Folder is true) |
| — Timeout | number | No | 10000 | Connection timeout in milliseconds. |
Download (download)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| Path | string | Yes | — | The file path of the file to download. Has to contain the full path. Supports expressions like {{ $json.path }}. |
Put Output File in Field (binaryPropertyName) | string | Yes | data | The name of the output binary field to put the file in. Names are case-sensitive — see the upstream node’s Binary Data panel for the exact names to use. |
| Options | collection | No | {} | Additional options for the download operation. |
| — Timeout | number | No | 10000 | Connection timeout in milliseconds. |
List (list)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| Path | string | Yes | / | Path of directory to list contents of. Supports expressions. |
| Recursive | boolean | Yes | false | Whether to recursively list all directories and files found within the directory. |
| Options | collection | No | {} | Additional options for the list operation. |
| — Timeout | number | No | 10000 | Connection timeout in milliseconds. |
Rename (rename)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| Old Path | string | Yes | — | The current path of the file or folder to rename or move. Supports expressions like {{ $json.oldPath }}. |
| New Path | string | Yes | — | The new path for the file or folder. Supports expressions. |
| Options | collection | No | {} | Additional options for the rename operation. |
| — Create Directories | boolean | No | false | Whether to recursively create destination directory when renaming an existing file or folder. |
| — Timeout | number | No | 10000 | Connection timeout in milliseconds. |
Upload (upload)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| Path | string | Yes | — | The file path of the file to upload. Has to contain the full path. Supports expressions like {{ $json.path }}. |
| Binary File | boolean | No | true | Whether to upload from binary data (true) or text content (false). |
Input Binary Field (binaryPropertyName) | string | Yes | data | The name of the input binary field containing the file to be uploaded. Names are case-sensitive — see the upstream node’s Binary Data panel for the exact names to use. (shown when Binary File is true) |
| File Content | string | No | — | The text content of the file to upload. Supports expressions like {{ $json.body }}. (shown when Binary File is false) |
| Options | collection | No | {} | Additional options for the upload operation. |
| — Timeout | number | No | 10000 | Connection timeout in milliseconds. |
All Operations
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| Protocol | options | No | ftp | File transfer protocol to use. |
Options: ftp, sftp | ||||
| Max Concurrency | number | No | 5 | Maximum number of items to process concurrently. Note: FTP/SFTP use a single connection, so items are processed sequentially over that connection regardless of this setting. |
Output Data
Each operation shapes the output item differently — three of the five discard the input item’s JSON, which is the most common surprise when building a pipeline around this node.
| Operation | Output |
|---|---|
download | One item. The item JSON passes through unchanged; the downloaded file is added as a binary property under the name you chose, alongside any binary the item already carried. The binary’s file name is taken from the remote path, and its MIME type is detected from that name. |
upload | One item. Both the JSON and the binary pass through unchanged — nothing is added, so a successful upload looks exactly like its input. |
list | Fans out — one output item per directory entry, and each item’s JSON replaces the input JSON with that entry’s own fields. Binary is not forwarded on those items. An empty directory instead produces a single item whose JSON is the input JSON plus entries: [], with binary forwarded. |
delete | One item whose JSON is replaced with { "success": true }. Binary is forwarded. |
rename | One item whose JSON is replaced with { "success": true }. Binary is forwarded. |
Directory entries always carry name, type (d for a directory, - for a file), size, path (the full path, assembled for you) and modifyTime. SFTP adds accessTime, rights, owner, group and longname. The remaining fields depend on what the server reports.
Reference the results downstream by expression, e.g. {{ $json.name }} after a list, or {{ $json.success }} after a delete.
Usage Examples
- Download a file from an SFTP server
- Upload a PDF to an FTP server
- List files in a remote directory
- Delete an old backup from SFTP
- Move a file to a different folder on the FTP server
Example Configuration
Download a file over SFTP into a named binary field:
{
"type": "ftp",
"parameters": {
"protocol": "sftp",
"operation": "download",
"path": "/remote/path/file.txt",
"binaryPropertyName": "downloadedFile",
"options": {
"timeout": 30000
}
}
}
Upload a binary file from an upstream node:
{
"type": "ftp",
"parameters": {
"protocol": "ftp",
"operation": "upload",
"path": "/remote/path/uploaded-file.pdf",
"binaryData": true,
"binaryPropertyName": "fileToUpload",
"options": {
"timeout": 60000
}
}
}
Upload text built from the item instead of a file:
{
"type": "ftp",
"parameters": {
"protocol": "sftp",
"operation": "upload",
"path": "/remote/path/{{ $json.slug }}.txt",
"binaryData": false,
"fileContent": "{{ $json.body }}",
"options": {
"timeout": 15000
}
}
}
Delete a single file:
{
"type": "ftp",
"parameters": {
"protocol": "ftp",
"operation": "delete",
"path": "/remote/path/file-to-delete.txt",
"options": {
"folder": false,
"timeout": 10000
}
}
}
Delete a folder and everything inside it:
{
"type": "ftp",
"parameters": {
"protocol": "sftp",
"operation": "delete",
"path": "/remote/path/folder-to-delete",
"options": {
"folder": true,
"recursive": true,
"timeout": 30000
}
}
}
Rename a file in place:
{
"type": "ftp",
"parameters": {
"protocol": "ftp",
"operation": "rename",
"oldPath": "/remote/path/old-filename.txt",
"newPath": "/remote/path/new-filename.txt",
"options": {
"createDirectories": true,
"timeout": 10000
}
}
}
List one directory:
{
"type": "ftp",
"parameters": {
"protocol": "sftp",
"operation": "list",
"path": "/remote/directory",
"recursive": false,
"options": {
"timeout": 20000
}
}
}
Walk a directory tree:
{
"type": "ftp",
"parameters": {
"protocol": "ftp",
"operation": "list",
"path": "/remote/directory",
"recursive": true,
"options": {
"timeout": 60000
}
}
}
Use SFTP for an encrypted transfer:
{
"type": "ftp",
"parameters": {
"protocol": "sftp",
"operation": "download",
"path": "/secure/path/confidential.txt",
"binaryPropertyName": "secureFile"
}
}
Give a large upload a longer timeout:
{
"type": "ftp",
"parameters": {
"protocol": "ftp",
"operation": "upload",
"path": "/uploads/large-file.zip",
"binaryData": true,
"binaryPropertyName": "largeFile",
"options": {
"timeout": 300000
}
}
}
Move a file into a folder that may not exist yet:
{
"type": "ftp",
"parameters": {
"protocol": "sftp",
"operation": "rename",
"oldPath": "/tmp/file.txt",
"newPath": "/archive/2024/file.txt",
"options": {
"createDirectories": true,
"timeout": 15000
}
}
}
Error Handling
| Mode | Behavior |
|---|---|
| stop | Halts workflow on first error |
| continue | Skips failed items, passes successful ones through |
| errorPort | Routes failed items to Error output port |
Tips
Transfer files between workflow items and remote FTP/SFTP servers — download, upload, list, delete, or rename files.
Behavior notes
- Protocol has to match the credential. FTP and SFTP are different services on different ports; pick the protocol the server actually speaks, and configure the matching credential fields.
- One connection per node run. The node opens a single connection, processes every item over it, and closes it at the end. Max Concurrency therefore does not make transfers overlap — leave it alone unless you have a reason.
- Paths must be absolute. Every path parameter expects the full remote path, not a path relative to the login directory.
- Uploading creates missing parent directories. Over SFTP they are created before the write; over FTP they are created after the server rejects the first attempt, then the upload is retried.
- Renaming only creates directories when you ask. Turn Create Directories on to have the destination folder created; leave it off and a move into a missing folder fails.
- Deleting a folder needs the Folder option. Set Folder on to target a directory, and add Recursive when the directory is not empty — without it, a non-empty directory fails to delete.
listchanges the item count. One input item becomes one output item per entry, so put a node that expects a single item before it, not after.- Recursive listing skips
.and..and walks every subdirectory it finds, which can be slow on large trees — raise the Timeout accordingly. - Upload succeeds silently. Because upload forwards its input untouched, check the Error output or the execution log rather than looking for a success flag on the item.
Frequently asked questions
Do I need separate credentials for FTP vs SFTP, or does one credential cover both?
The credential type (ftpApi) covers both, but the protocol you select in the node must match what the server actually runs — FTP and SFTP are different services that listen on different ports. Picking SFTP in the node while your server only speaks plain FTP will fail at connection time, so confirm the protocol with whoever runs the server before configuring the credential.
How do I know whether an upload succeeded? The output item looks identical to the input.
That's by design: the upload operation forwards its input item untouched rather than returning a success flag. To catch failures, wire up the Error output or check the execution log. If nothing appears on the Error output, the upload completed without error.
I'm using the list operation and now downstream nodes are receiving more items than expected — what happened?
List expands one input item into one output item per directory entry, so the item count changes. Any node placed after a list step needs to handle multiple items. If a downstream node expects a single consolidated item, aggregate or limit the results before passing them on.
Do I need to create the destination directory before uploading, or does the node handle that?
The node creates missing parent directories automatically during upload. Over SFTP they are created before the write; over FTP the node first attempts the upload, and if the server rejects it due to a missing directory the node creates the directory and retries. For rename/move operations you must explicitly turn on the Create Directories option, otherwise moving a file into a non-existent folder will fail.
How do I delete a non-empty folder instead of a single file?
Set the Folder option to target a directory rather than a file, then also enable Recursive — without Recursive, the node will fail if the directory contains any files or subdirectories. Deleting an empty directory works with Folder alone; Recursive is only required when the directory has contents.
Build with the FTP node
Drop it into a workflow, wire it to an agent, or call it on a schedule. You'll need FTP / SFTP credentials first.
Open BusyBotLast updated . Spotted something wrong? Tell us.