Is SFTP possible on ESP32 using Arduino IDE?

Hi,

I am using ESP32 with Arduino IDE and I need to download a bin files from a server(S3 bucket) using SFTP.

I tried using libssh, but it only supports:

  • SSH

  • SCP

It does not support SFTP.

My server only allows SFTP, so SCP will not work.

Is it possible to use SFTP on ESP32?
Is there any library available for Arduino IDE?

Has anyone successfully implemented SFTP on ESP32?

Any suggestions or alternative solutions are welcome.

Thank you.

I moved your topic to an appropriate forum category @novalriod123.

In the future, when creating a topic please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

try asking on the ESP32 Arduino forum?

consider using a Raspberry PI 4 or 5?

The IDE is not really a factor. It's the library.

libssh does support SFTP. I just installed the port; the README says

Last ported 10th February 2026, built with libssh commit ca9c055d, branch
-stable-0.11, version libssh-0.11.4.

Here's sftp.c on that branch; full of sftp_ functions. It just was not ported over to ESP32.

There may be a specific technical reason why not. But you can try doing it yourself. Download four files: right-click and Save As using the "plain" link at the end of the third-ish line that starts with "blob" on each page, just above the file content

With the four files in your Downloads directory, copy them into the existing library. For example, if your sketchbook is at ~/Arduino, then the library's src directory is at ~/Arduino/libraries/LibSSH-ESP32/src. The directory structure is a little different: the content of include is merged with src, so that the paths are

  • src/sftp.c (as siblings of scp.c)
  • src/sftp_common.c
  • src/libssh/sftp.h (as siblings of scp.h)
  • src/libssh/sftp_priv.h

At the top of sftp.c, after the comment blocks is #include "config.h" -- replace it to match the other ported .c files, with the port-specific config

#include "libssh_esp32_config.h"

Make the same change to sftp_common.c. The last line of both files

#endif /* WITH_SFTP */

indicates a conditional compilation flag. It's in the aforementioned src/libssh_esp32_config.h, at line 236

/* Define to 1 if you want to enable SFTP */
/* #undef WITH_SFTP */

so change that to

/* Define to 1 if you want to enable SFTP */
#define WITH_SFTP 1

The file is duplicated as src/libssh/libssh_esp32_config.h. You can update both, but it doesn't look like it should matter.

Now take that bit of SFTP tutorial (in the first link above) and put it in an empty sketch

#include <libssh_esp32.h>
#include <libssh/sftp.h>

int sftp_helloworld(ssh_session session) {
  sftp_session sftp;
  int rc;
 
  sftp = sftp_new(session);
  if (sftp == NULL)
  {
    Serial.printf("Error allocating SFTP session: %s\n",
            ssh_get_error(session));
    return SSH_ERROR;
  }
 
  rc = sftp_init(sftp);
  if (rc != SSH_OK)
  {
    Serial.printf("Error initializing SFTP session: code %d.\n",
            sftp_get_error(sftp));
    sftp_free(sftp);
    return rc;
  }
 
  // ...
 
  sftp_free(sftp);
  return SSH_OK;
}

void setup() {
  Serial.begin(115200);
  ssh_session session;
  auto result = sftp_helloworld(session);
  Serial.println(result);
}

void loop() {}

It compiles, but does not link successfully (reformatted for clarity):

/esp32-arduino-libs/idf-release_v5.1-632e0c2a/esp32/lib
  /liblwip.a(ip6.c.obj): in function `ip6_input':
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/lwip/lwip/src/core/ipv6
  /ip6.c:547: undefined reference to `lwip_hook_ip6_input'

Note that /home/runner is a path on the build machine that built ip6.c in LwIP that is a component of the ESP32 IDF. It's this bit

using the two arguments for the named function

Something in SFTP causes this IPv6 code to be linked in, but it is incomplete for a regular sketch. Instead of trying to figure that out and disable it, it's simpler to provide a do-nothing stub in the sketch

extern "C" int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp) {
  Serial.printf("hey, something is calling %s\n", __func__);
  return 0;
}

That built for me. Does it work? I have no idea.

If there is not a particular reason for S you can use just FTP server. It's pretty handy in local environments, for example, you can access the files with Windows Explorer.

you can check this if it helps, it has sftp implemented for esp32/esp8266 both : GitHub - Suraj151/pdi-framework: Portable Device Interface (PDI) framework stack for easy configurable applications running over avr, esp8266, esp32 devices. Designed to manage services such as WiFi, HTTP/S, MQTT, SFTP, SSH server, Telnet server, OTA, GPIO, Serial, CMD terminal and much more handled with configurable Task Scheduler. · GitHub