Using cURL for FTP and SFTP transfers enables scripted uploads, downloads, and directory listings without interactive clients. Automating file movement in this way supports scheduled jobs, integration with build pipelines, and quick ad‑hoc transfers using a single, consistent command-line tool. Choosing between plain FTP and encrypted SFTP balances convenience and security based on the data and network environment.

The cURL command encodes the protocol, host, and path directly in the URL, such as ftp://ftp.example.net/ or sftp://sftp.example.net/home/user/. Options like --upload-file, --remote-name, and --continue-at control how files move between the local system and the remote server, while --user and key options supply credentials for authentication. The same syntax pattern applies across supported platforms, which keeps usage consistent on Linux, macOS, and Windows terminals.

Plain FTP exposes credentials and data in clear text, so it suits only non-sensitive content on trusted networks, whereas SFTP wraps traffic inside SSH with strong encryption. Firewalls, proxies, and server configuration can affect which protocol and ports are reachable, and large or unstable transfers often benefit from resume support rather than starting again from byte zero. Switching between FTP and SFTP typically involves changing only the URL scheme and authentication flags.

Steps to use cURL with FTP and SFTP:

  1. Open a terminal session in an environment where cURL can reach the target FTP or SFTP server.
  2. Upload a file to an FTP directory using basic authentication.
    $ curl --upload-file example.txt "ftp://ftp.example.net/" --user user:password
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                    Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
    100    29    0     0  100    29      0   1241 --:--:-- --:--:-- --:--:--  1260

    FTP transfers, including --user credentials and file contents, travel unencrypted and can be intercepted on untrusted networks.

  3. Download a file from an FTP directory while preserving the remote filename.
    $ curl --remote-name "ftp://ftp.example.net/example.txt" --user user:password
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                    Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
    100    29  100    29    0     0   1202      0 --:--:-- --:--:-- --:--:--  1208

    --remote-name stores the file using the server-side name instead of requiring a local filename argument.

  4. List the contents of an FTP directory to confirm paths before transferring files.
    $ curl --silent "ftp://ftp.example.net/" --user user:password
    -rw-r--r--    1 1001     1001           29 Jan 10 06:16 example.txt
    -rw-r--r--    1 1001     1001          162 Jan 10 06:13 project-2025-12-archive.tar.gz
    drwx------    3 1001     1001         4096 Jan 10 06:13 releases
    -rw-r--r--    1 1001     1001       524288 Jan 10 05:41 report.tar.gz

    Directory listings reveal exact filenames, sizes, and timestamps, which helps avoid typos and accidental overwrites.

  5. Upload a file securely to an SFTP home directory using password authentication.
    $ curl --upload-file example.txt "sftp://sftp.example.net/home/user/example.txt" --user user:password
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                    Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
    100    29    0     0  100    29      0    287 --:--:-- --:--:-- --:--:--   290
    100    29    0     0  100    29      0    287 --:--:-- --:--:-- --:--:--   287

    SFTP uses the same username and password concept as SSH while encrypting both credentials and data in transit.

  6. Download a file from an SFTP directory using the same URL pattern as FTP.
    $ curl --remote-name "sftp://sftp.example.net/home/user/example.txt" --user user:password
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                    Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
    100    29  100    29    0     0    276      0 --:--:-- --:--:-- --:--:--   276
    100    29  100    29    0     0    276      0 --:--:-- --:--:-- --:--:--   276

    Reusing the same flags and layout across FTP and SFTP reduces mistakes when switching protocols.

  7. List files on an SFTP directory to inspect remote content and confirm transfer locations.
    $ curl --silent "sftp://sftp.example.net/home/user/" --user user:password
    drwx------    2 root     root         4096 Jan 10 06:14 .ssh
    drwx------    2 user     user         4096 Jan 10 05:51 .cache
    -rw-r--r--    1 user     user          220 Mar 31  2024 .bash_logout
    drwxr-xr-x    1 root     root         4096 Jan 10 04:44 ..
    -rw-r--r--    1 user     user         3771 Mar 31  2024 .bashrc
    -rw-r--r--    1 user     user           29 Jan 10 06:16 example.txt
    drwxr-x---    5 user     user         4096 Jan 10 06:14 .
    drwxr-xr-x    3 user     user         4096 Jan 10 06:13 public_html
    -rw-r--r--    1 user     user          162 Jan 10 06:13 project-2025-12-archive.tar.gz
    -rw-r--r--    1 user     user          807 Mar 31  2024 .profile

    Listing the directory after uploads confirms that files landed in the intended path with the expected ownership.

  8. Create a partial FTP download when preparing to resume a transfer.
    $ curl --range 0-262143 --output report.tar.gz "ftp://ftp.example.net/report.tar.gz" --user user:password
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
    100  256k  100  256k    0     0  10.7M      0 --:--:-- --:--:-- --:--:-- 10.8M

    Partial downloads leave a local file that cURL can reuse as the starting point for a resumed transfer.

  9. Resume a partial FTP download instead of restarting from the beginning when supported by the server.
    $ curl --continue-at - --remote-name "ftp://ftp.example.net/report.tar.gz" --user user:password
    ** Resuming transfer from byte position 262144
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                    Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
    100  256k  100  256k    0     0  11.1M      0 --:--:-- --:--:-- --:--:-- 11.3M

    Resuming requires a matching partial local file; mismatched content produces corrupted downloads that often fail checksum or integrity tests.

  10. Upload a file over SFTP using existing SSH key material instead of a password.
    $ curl --upload-file example.txt "sftp://sftp.example.net/home/user/example.txt" --key /root/.ssh/sg_curl --pubkey /root/.ssh/sg_curl.pub --user user:
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                    Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
    100    29    0     0  100    29      0    361 --:--:-- --:--:-- --:--:--   362
    100    29    0     0  100    29      0    361 --:--:-- --:--:-- --:--:--   361

    Key-based authentication keeps passwords out of scripts and reuses the same OpenSSH keys employed for interactive SSH logins.

  11. Verify successful transfers by listing the remote SFTP directory again and checking for the expected filenames.
    $ curl --silent "sftp://sftp.example.net/home/user/" --user user:password
    drwx------    2 user     user         4096 Jan 10 06:14 .ssh
    drwx------    2 user     user         4096 Jan 10 05:51 .cache
    -rw-r--r--    1 user     user          220 Mar 31  2024 .bash_logout
    drwxr-xr-x    1 root     root         4096 Jan 10 04:44 ..
    -rw-r--r--    1 user     user         3771 Mar 31  2024 .bashrc
    -rw-r--r--    1 user     user           29 Jan 10 06:16 example.txt
    drwxr-x---    5 user     user         4096 Jan 10 06:14 .
    drwxr-xr-x    3 user     user         4096 Jan 10 06:13 public_html
    -rw-r--r--    1 user     user          162 Jan 10 06:13 project-2025-12-archive.tar.gz
    -rw-r--r--    1 user     user          807 Mar 31  2024 .profile

    Reliable success signals include completed progress meters without errors and the presence of transferred files in directory listings with the correct size.