Reference · Tools

FTP

Transfer files to and from remote servers via FTP or SFTP protocols.

Action (binary) Development v1 Binary data

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

DirectionPort(s)
InputInput
OutputOutput, Error

Credentials

This tool requires FTP / SFTP credentials. See the Credentials Guide for setup instructions.

Operations

OperationValueDescription
DeletedeleteDelete a file or folder
DownloaddownloadDownload a file
ListlistList folder content
RenamerenameRename/move a file or folder
UploaduploadUpload a file

Parameters

Delete (delete)

ParameterTypeRequiredDefaultDescription
PathstringYesThe file path of the file to delete. Has to contain the full path. Supports expressions like {{ $json.path }}.
OptionscollectionNo{}Additional options for the delete operation.
— FolderbooleanNofalseWhether folders can be deleted.
— RecursivebooleanNofalseWhether to remove all files and directories in target directory. (shown when Folder is true)
— TimeoutnumberNo10000Connection timeout in milliseconds.

Download (download)

ParameterTypeRequiredDefaultDescription
PathstringYesThe file path of the file to download. Has to contain the full path. Supports expressions like {{ $json.path }}.
Put Output File in Field (binaryPropertyName)stringYesdataThe 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.
OptionscollectionNo{}Additional options for the download operation.
— TimeoutnumberNo10000Connection timeout in milliseconds.

List (list)

ParameterTypeRequiredDefaultDescription
PathstringYes/Path of directory to list contents of. Supports expressions.
RecursivebooleanYesfalseWhether to recursively list all directories and files found within the directory.
OptionscollectionNo{}Additional options for the list operation.
— TimeoutnumberNo10000Connection timeout in milliseconds.

Rename (rename)

ParameterTypeRequiredDefaultDescription
Old PathstringYesThe current path of the file or folder to rename or move. Supports expressions like {{ $json.oldPath }}.
New PathstringYesThe new path for the file or folder. Supports expressions.
OptionscollectionNo{}Additional options for the rename operation.
— Create DirectoriesbooleanNofalseWhether to recursively create destination directory when renaming an existing file or folder.
— TimeoutnumberNo10000Connection timeout in milliseconds.

Upload (upload)

ParameterTypeRequiredDefaultDescription
PathstringYesThe file path of the file to upload. Has to contain the full path. Supports expressions like {{ $json.path }}.
Binary FilebooleanNotrueWhether to upload from binary data (true) or text content (false).
Input Binary Field (binaryPropertyName)stringYesdataThe 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 ContentstringNoThe text content of the file to upload. Supports expressions like {{ $json.body }}. (shown when Binary File is false)
OptionscollectionNo{}Additional options for the upload operation.
— TimeoutnumberNo10000Connection timeout in milliseconds.

All Operations

ParameterTypeRequiredDefaultDescription
ProtocoloptionsNoftpFile transfer protocol to use.
Options: ftp, sftp
Max ConcurrencynumberNo5Maximum 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.

OperationOutput
downloadOne 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.
uploadOne item. Both the JSON and the binary pass through unchanged — nothing is added, so a successful upload looks exactly like its input.
listFans 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.
deleteOne item whose JSON is replaced with { "success": true }. Binary is forwarded.
renameOne 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

ModeBehavior
stopHalts workflow on first error
continueSkips failed items, passes successful ones through
errorPortRoutes 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.
  • list changes 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 BusyBot

Last updated . Spotted something wrong? Tell us.