SFTP is a secure way to move files between systems, vendors, customers, and internal applications. It runs over SSH, encrypts the transfer session, and supports authentication methods that work well for automated file exchange.

PHP can connect to SFTP too, but PHP doesn’t include SFTP support by default. For most PHP projects, the cleanest route is to use phpseclib, a PHP secure communications library that includes SFTP support and can be installed with Composer.

In this guide, we’ll build a reusable PHP SFTP client that can connect to an SFTP server, authenticate, list files, upload files, download files, delete remote files, and run the whole flow from one PHP script.

This is handy when a PHP application needs to exchange invoices, reports, exports, customer files, partner uploads, EDI files, backups, or other business data without sending files over plain FTP.


PHP SFTP requirements

Before you connect to SFTP in PHP, you’ll need three things:

  • A PHP project with Composer available
  • The phpseclib/phpseclib package
  • An SFTP endpoint with a host, port, username, and password or key-based access

If you don’t already have an SFTP server, SFTP To Go gives you a managed SFTP endpoint with cloud storage, credentials and permissions, audit logs, web portal access, and support for automated file workflows. You can set it up in 30 seconds, and focus on the PHP integration instead of running and maintaining the SFTP server yourself.

PHP doesn’t come bundled with the SFTP libraries from the get-go, so we’ll need to install the required library, phpseclib, using composer.

$ composer require phpseclib/phpseclib

In accordance with the 12 factor app cloud development methodology, you should explicitly define your app’s dependencies, which would make our composer.json file look like this:

{
 "require": {
    "phpseclib/phpseclib": "^3.0"
    }
}

Once the dependency is installed, you can start building the SFTP client. Now the real fun begins!


How to create an SFTP connection in PHP

The first step is to create a small PHP class that wraps the SFTP connection. This keeps connection handling, authentication, upload, download, and file-listing logic in one place instead of scattering SFTP calls through the application.

The class in this guide uses phpseclib3\Net\SFTP to connect to the remote SFTP server. It accepts a host and port, creates the SFTP session, and throws an exception if the connection fails.

It also includes methods for password authentication, public-key or agent-style authentication, and disconnection.

<?php
class SFTPClient
{
  private $sftp;

  public function __construct($host, $port=22)
  {
    $this->sftp = new SFTP($host, $port);
    if (!$this->sftp->isConnected())
      throw new Exception("Failed to connect to ${host} on port ${port}.");
  }

  // Login with user and password
  public function auth_password($username, $password)
  {
    if (!$this->sftp->login($username, $password))
      throw new Exception("Failed to authenticate with username $username " .
                          "and password.");
  }

  // Login with SSH agent
  public function auth_agent($username)
  {
    if (!$this->sftp->login($username))
      throw new Exception("Failed to authenticate with username $username " .
                          "and public key.");
  }

  // Disconnect session
  public function disconnect()
  {
    $this->sftp->disconnect();
  }
 }

?>

connect-class.php

This gives you the start of a reusable PHP SFTP client. In a production app, keep credentials in environment variables or a secrets manager rather than hardcoding them into the script.


How to parse SFTP credentials from an environment variable

The original example uses the SFTPTOGO_URL environment variable to store the SFTP connection details in URI format:

sftp://user:password@host

That keeps connection details outside the code and makes the script easier to run across local development, staging, and production.

The main function parses the URL, extracts the username, password, host, and port, then prepares the client connection.

<?php
function main()
{
  $raw_url = getenv('SFTPTOGO_URL');

  // Parse URL
  $parsed_url = parse_url($raw_url);

  if ($parsed_url === false)
  {
    fwrite(STDERR, "Failed to parse SFTP To Go URL.\n");
    exit(1);
  }

  // Get user name and password
  $user = isset($parsed_url['user']) ? $parsed_url['user'] : null;
  $pass = isset($parsed_url['pass']) ? $parsed_url['pass'] : null;

  // Parse Host and Port
  $host = isset($parsed_url['host']) ? $parsed_url['host'] : null;

  // Port is always 22
  $port = isset($parsed_url['port']) ? $parsed_url['port'] : 22;

  fwrite(STDOUT, "Connecting to [${host}] ...\n");
}

main();

?>

connect-main.php

Using an environment variable is also handy when deploying PHP apps to cloud platforms. Your code stays the same, while each environment can provide its own SFTP credentials.


How to list files on an SFTP server with PHP

Once the connection works, the next common task is listing files in a remote directory.

This is useful when your PHP app needs to check whether a partner uploaded a file, inspect an inbound folder, find the newest file, or process everything waiting in a remote directory.

The example below adds a listFiles() method that calls nlist() on the remote directory and prints the remote file names.

<?php
  // List remote directory files
  function listFiles($remote_dir) {
    $tempArray = array();

    fwrite(STDOUT, "Listing [${remote_dir}] ...\n\n");

    $files = $this->sftp->nlist($remote_dir);
    foreach ($files as $file) {
      $filetype = $this->sftp->is_dir($file) ? 'dir' : 'file';
      $modTime = '';
      $size = sprintf("%.2f", $this->sftp->size($file));

      if ($filetype == "dir") {
        $file .= '/';
        $modTime = '';
        $size = "PRE";
      }

      $tempArray[] = $file;

      printf("%19s %12s %s\n", $modTime, $size, $file);
    }

    return $tempArray;
  }

?>

listfiles.php

For a production workflow, you may want to add filtering, file-age checks, naming checks, or duplicate handling. For example, a PHP app might only process files ending in .csv, ignore temporary files, or move processed files into an archive folder.


How to upload a file to SFTP with PHP

Uploading files over SFTP is one of the most common PHP automation tasks.

A PHP app may need to send invoices, reports, product feeds, claim files, customer documents, EDI files, or batch exports to another system. With SFTP, those files move over an encrypted SSH session instead of plain FTP. Much better!

The uploadFile() method in the original guide reads a local file, then sends it to the remote SFTP path with put().

<?php
  // Upload local file to remote file
  public function uploadFile($local_file, $remote_file)
  {
    fwrite(STDOUT, "Uploading [${local_file}] to [${remote_file}] ...\n");

    $data_to_send = file_get_contents($local_file);
    if ($data_to_send === false)
      throw new Exception("Could not open local file: $local_file.");

    if (!$this->sftp->put($remote_file, $data_to_send))
      throw new Exception("Could not send data from file: $local_file.");
  }
?>

uploadfile.php

For practical use, check that the local file exists before upload, use predictable remote paths, avoid overwriting files unless that’s intentional, and log successful and failed uploads.

When you choose SFTP To Go, uploaded files land in managed S3 cloud storage, with access controls and audit logs around file activity.


How to download a file from SFTP with PHP

Downloading from SFTP is the other half of many automated workflows.

A PHP app might collect vendor reports, customer files, transaction exports, lab files, EDI files, scheduled data feeds, or partner uploads from a remote SFTP directory.

The downloadFile() method uses get() to read the remote file, then writes it to a local path.

<?php
  // Download remote file to local file
  public function downloadFile($remote_file, $local_file)
  {
    fwrite(STDOUT, "Downloading [${remote_file}] to [${local_file}] ...\n");

    $contents = $this->sftp->get($remote_file);
    if ($contents === false)
      throw new Exception("Could not open remote file: $remote_file.");

    file_put_contents($local_file, $contents);
  }

?>

downloadfile.php

Be careful with what happens after the download. If the next step is a database import, parser, validation job, or upcoming process, don’t delete the remote copy until that step has completed successfully.

A safer pattern is to:

  • Download the file
  • Validate or process it
  • Log the result
  • Move the remote copy into a processed or archive folder
  • Move failed files into an error folder for review

That avoids duplicate processing without losing the source file when the job fails halfway through.


Full PHP SFTP example

The full script brings the pieces together.

It connects to the SFTP server, authenticates, lists the current directory, uploads a local file, downloads the remote file, and deletes the remote copy.

That’s it! If you 'd like to run the entire program from start to finish, copy the following code and save it as main.php:

<?php

use phpseclib3\Net\SFTP;

class SFTPClient
{
  private $sftp;

  public function __construct($host, $port=22)
  {
    $this->sftp = new SFTP($host, $port);
    if (!$this->sftp->isConnected())
      throw new Exception("Failed to connect to ${host} on port ${port}.");
  }

  // Login with user and password
  public function auth_password($username, $password)
  {
    if (!$this->sftp->login($username, $password))
      throw new Exception("Failed to authenticate with username $username " .
                          "and password.");
  }

  // Login with SSH agent
  public function auth_agent($username)
  {
    if (!$this->sftp->login($username))
      throw new Exception("Failed to authenticate with username $username " .
                          "and public key.");
  }

  // Disconnect session
  public function disconnect()
  {
    $this->sftp->disconnect();
  }
  
  // List remote directory files
  function listFiles($remote_dir) {
    $tempArray = array();

    fwrite(STDOUT, "Listing [${remote_dir}] ...\n\n");

    $files = $this->sftp->nlist($remote_dir);
    foreach ($files as $file) {
      $filetype = $this->sftp->is_dir($file) ? 'dir' : 'file';
      $modTime = '';
      $size = sprintf("%.2f", $this->sftp->size($file));

      if ($filetype == "dir") {
        $file .= '/';
        $modTime = '';
        $size = "PRE";
      }

      $tempArray[] = $file;

      printf("%19s %12s %s\n", $modTime, $size, $file);
    }

    return $tempArray;
  }

  // Upload local file to remote file
  public function uploadFile($local_file, $remote_file)
  {
    fwrite(STDOUT, "Uploading [${local_file}] to [${remote_file}] ...\n");

    $data_to_send = file_get_contents($local_file);
    if ($data_to_send === false)
      throw new Exception("Could not open local file: $local_file.");

    if (!$this->sftp->put($remote_file, $data_to_send))
      throw new Exception("Could not send data from file: $local_file.");
  }

  // Download remote file to local file
  public function downloadFile($remote_file, $local_file)
  {
    fwrite(STDOUT, "Downloading [${remote_file}] to [${local_file}] ...\n");

    $contents = $this->sftp->get($remote_file);
    if ($contents === false)
      throw new Exception("Could not open remote file: $remote_file.");

    file_put_contents($local_file, $contents);
  }

  // Delete remote file
  public function deleteFile($remote_file){
    fwrite(STDOUT, "Deleting [${remote_file}] ...\n");
    $this->sftp->delete($remote_file);
  }
}

function main()
{
  $raw_url = getenv('SFTPTOGO_URL');

  // Parse URL
  $parsed_url = parse_url($raw_url);

  if ($parsed_url === false)
  {
    fwrite(STDERR, "Failed to parse SFTP To Go URL.\n");
    exit(1);
  }

  // Get user name and password
  $user = isset($parsed_url['user']) ? $parsed_url['user'] : null;
  $pass = isset($parsed_url['pass']) ? $parsed_url['pass'] : null;

  // Parse Host and Port
  $host = isset($parsed_url['host']) ? $parsed_url['host'] : null;

  // Port is always 22
  $port = isset($parsed_url['port']) ? $parsed_url['port'] : 22;

  fwrite(STDOUT, "Connecting to [${host}] ...\n");

  try
  {
    $client = new SFTPClient($host, $port);
    $client->auth_password($user, $pass);

    //*
    //* List working directory files
    //*
    $client->listFiles(".");

    //*
    //* Upload local file to remote file
    //*
    $client->uploadFile("./local.txt", "./remote.txt");

    //*
    //* Download remote file to local file
    //*
    $client->downloadFile("./remote.txt", "./download.txt");

    //*
    //* Delete remote file
    //*
    $client->deleteFile("./remote.txt");
  }
  catch (Exception $e)
  {
    echo $e->getMessage() . "\n";
  }
}

main();

?>

main.php

To run the code, use the command:

php main.php

You can also clone our repo or check out more code samples on Github.

This is enough for a working PHP SFTP test: connect, authenticate, list files, upload, download, delete, and handle basic errors. Voila!


PHP SFTP best practices for real workflows

The example above proves the connection and file operations, but a real workflow needs stronger handling around credentials, paths, logging, and recovery, especially in industries where data compliance is a factor.

Start with credentials. Keep passwords and keys out of the codebase. Use environment variables, your platform’s config system, or a secrets manager. For recurring automation, SSH key authentication is often easier to manage than shared passwords.

Then look at folder structure. A small amount of order helps once files start moving every day. Separate inbound, outbound, processed, and error files. Use file names that tell you what the file is, where it came from, and when it was created.

For PHP SFTP automation, log the parts you’ll need if something fails:

  • Connection attempts
  • Authentication failures
  • Uploaded file names
  • Downloaded file names
  • Remote paths
  • Delete or archive actions
  • Failed file operations
  • Missing expected files

If the workflow supports a business process, don’t rely only on the PHP script. The SFTP service should also give you access controls, protected storage, and audit records. SFTP To Go fits here because your PHP code handles the file work, while the service handles the transfer endpoint, storage, access controls, audit logs, APIs, and webhooks.


PHP SFTP troubleshooting tips

Most PHP SFTP problems come from connection details, credentials, paths, or permissions.

  • If the script can’t connect, check the host, port, DNS, firewall rules, and whether the PHP environment can reach the SFTP endpoint.
  • If login fails, check the username, password, SSH key, account status, and whether the credential belongs to the SFTP user you think it belongs to.
  • If listing, uploads, or downloads fail, check the path first. SFTP users are often restricted to specific home directories, so the path you see in your client may not match the full server path behind it.

A quick checklist:

  • Is phpseclib/phpseclib installed?
  • Is Composer autoloading included where needed?
  • Is the SFTP host correct?
  • Is the port correct, usually 22?
  • Are the username and password or SSH key valid?
  • Does the user have access to the remote folder?
  • Does the remote path exist?
  • Is the local file path correct?
  • Is the local directory writable for downloads?
  • Are failed operations being logged clearly?

If the answer is still hiding from you, phpseclib’s diagnostic logs can help you see what is happening during connection and authentication.


When should you use PHP with SFTP?

Use PHP with SFTP when the PHP application runs the file workflow.

That might be a scheduled import, a nightly export, a customer file download, a vendor upload, an EDI handoff, a backup job, or a report sent to another system.

SFTP is a good fit when the file is sensitive in nature, has business value, or simply shouldn’t move across the network in clear text. It also works well for recurring automation because it supports scripts, SSH authentication, predictable folder structures, and controlled access.

PHP isn't the only way to do this. Some teams use shell scripts, workers, queues, cron jobs, integration platforms, or serverless functions. But if the file workflow belongs close to a PHP app, phpseclib is a sensible way to add SFTP without adding a separate process.

You can also connect to SFTP in Java, Node.js, Golang, Ruby on Rails, C#, and Python.


How SFTP To Go supports PHP SFTP workflows

SFTP To Go gives PHP applications a managed SFTP endpoint without making your team run the SFTP server.

That helps when your PHP script needs to upload, download, list, or process files, but your team also needs storage, access controls, audit logs, and a practical way to manage partners or automated systems.

SFTP To Go supports SFTP, FTPS, S3 access, HTTPS/web portal access, and managed cloud storage. Developers can automate with SFTP or APIs, while non-technical users can use browser-based web portal access where needed.

For PHP-based workflows, that means you can:

  • Connect over SFTP from PHP
  • Store files in managed cloud storage
  • Separate access by user or folder
  • Review login and file activity in audit logs
  • Use APIs for management and audit-log export workflows
  • Use webhooks for upload, directory creation, download, and deletion events
  • Avoid maintaining your own SFTP server

The PHP code handles the file operations. SFTP To Go handles the managed transfer environment around those operations.


In conclusion

The script above is designed to get you moving quickly. Once the PHP connection works, you’ve got the basic shape of the workflow: connect, authenticate, list, upload, download, and close the session cleanly.

From there, make the script safer to run in a real file process. Keep credentials out of the code, use clear file names, log uploads and downloads, handle failed transfers, and decide where each file should go after it’s been processed.

If you want to test the code without maintaining your own SFTP server, create a managed SFTP endpoint with SFTP To Go and use the same PHP pattern from this guide.


Frequently asked questions

How do I connect to SFTP in PHP?

You can connect to SFTP in PHP by installing phpseclib with Composer, importing phpseclib3\Net\SFTP, creating a new SFTP connection with the server host and port, and then logging in with a username and password or SSH key.

Does PHP support SFTP by default?

PHP does not include built-in SFTP support by default. The common approach is to use a library such as phpseclib, or to use the SSH2 extension where it is available. This guide uses phpseclib because it can be installed with Composer and works well for portable PHP projects.

What is phpseclib?

phpseclib is a PHP secure communications library that provides SSH, SFTP, cryptography, and related features. For SFTP in PHP, phpseclib provides the phpseclib3\Net\SFTP class.

How do I install phpseclib for SFTP in PHP?

Install phpseclib with Composer by running composer require phpseclib/phpseclib. Then include Composer’s autoloader in your PHP script and import phpseclib3\Net\SFTP.

Can PHP upload files to SFTP?

Yes. PHP can upload files to SFTP with phpseclib by connecting to the SFTP server, authenticating, reading the local file, and using the SFTP put() method to write it to the remote path.

Can PHP download files from SFTP?

Yes. PHP can download files from SFTP with phpseclib by using the SFTP get() method to read the remote file and then writing the contents to a local file path.

Can PHP list files on an SFTP server?

Yes. PHP can list files on an SFTP server with phpseclib by using methods such as nlist() after connecting and authenticating to the SFTP server.

Can PHP delete files from an SFTP server?

Yes. PHP can delete files from an SFTP server with phpseclib by calling the SFTP delete() method with the remote file path.

Should I use password or SSH key authentication for PHP SFTP?

Both can work, but SSH key authentication is often better for automated workflows because it avoids putting shared passwords into scripts. Passwords and SSH keys still need proper storage, rotation, and access control.

What is the default SFTP port in PHP?

The default SFTP port is usually port 22 because SFTP runs over SSH. If your SFTP provider uses a different port, pass that port when creating the SFTP connection.

Can I use SFTP To Go with PHP?

Yes. You can use SFTP To Go as the managed SFTP endpoint for a PHP application. Your PHP script connects over SFTP, while SFTP To Go provides managed cloud storage, access controls, audit logs, APIs for management and audit-log export workflows, webhooks for file events, and browser-based file access around the transfer workflow.