{"id":15659,"library":"jsftp","title":"jsftp: A Node.js FTP Client","description":"jsftp is a client library for the File Transfer Protocol (FTP) specifically designed for Node.js environments. It emphasizes correctness, clarity, and conciseness, providing both low-level access to raw FTP commands and higher-level convenience methods for common operations like file transfers and directory listings. The current stable version is 2.1.3, released on an as-needed basis for bug fixes and feature enhancements, with previous major versions dropping older Node.js compatibility and updating APIs. A key differentiator is its integration with Node.js streaming APIs, allowing for efficient handling of file data. It exposes the underlying FTP protocol responses with `code` and `text` properties, giving developers granular control and insight into server interactions.","status":"active","version":"2.1.3","language":"javascript","source_language":"en","source_url":"https://github.com/sergi/jsftp","tags":["javascript","ftp","protocol","files","server","client","async"],"install":[{"cmd":"npm install jsftp","lang":"bash","label":"npm"},{"cmd":"yarn add jsftp","lang":"bash","label":"yarn"},{"cmd":"pnpm add jsftp","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"This library is primarily designed for CommonJS. While Node.js supports ESM, the primary usage pattern demonstrated is using `require()` to import the constructor function.","wrong":"import JsFtp from 'jsftp';","symbol":"jsftp (constructor)","correct":"const JsFtp = require('jsftp');"},{"note":"The imported `jsftp` is a constructor function and must be called with `new` to create an FTP client instance.","wrong":"const ftp = jsftp({ host: '...' });","symbol":"JsFtp instance","correct":"const ftp = new JsFtp({ host: '...' });"},{"note":"All native FTP commands are accessed via the `ftp.raw(command, [...args], callback)` method. There are convenience methods for common operations, but direct protocol commands use `raw`.","wrong":"ftp.quit((err, data) => { /* ... */ });","symbol":"raw command method","correct":"ftp.raw('quit', (err, data) => { /* ... */ });"}],"quickstart":{"code":"const JsFtp = require('jsftp');\n\nconst Ftp = new JsFtp({\n  host: process.env.FTP_HOST ?? 'localhost',\n  port: parseInt(process.env.FTP_PORT ?? '21', 10),\n  user: process.env.FTP_USER ?? 'anonymous',\n  pass: process.env.FTP_PASS ?? '@anonymous'\n});\n\nFtp.on('error', err => {\n  console.error('FTP Client Error:', err);\n  Ftp.destroy(); // Ensure the connection is closed on error\n});\n\nFtp.raw('syst', (err, data) => {\n  if (err) {\n    return console.error('Failed to get system info:', err);\n  }\n  console.log('System Info:', data.text);\n\n  Ftp.raw('quit', (err) => {\n    if (err) {\n      return console.error('Failed to quit:', err);\n    }\n    console.log('Successfully disconnected from FTP server.');\n  });\n});","lang":"javascript","description":"This code demonstrates how to establish a connection to an FTP server, retrieve its system information using a raw command, and then gracefully disconnect. It uses environment variables for host, port, user, and password for secure configuration."},"warnings":[{"fix":"Review the documentation for `jsftp` v2.0.0 to understand the new `raw` API and adapt your code accordingly. Responses now consistently return an object with `code` and `text` properties.","message":"The `raw` API underwent significant changes in version 2.0.0. Code relying on the exact structure or behavior of `raw` command responses from prior versions may break.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure your Node.js environment is at least version 6.x or newer, as specified in the package's engine requirements (`engines.node: \">=6\"`).","message":"Compatibility for Node.js versions older than 0.8 was dropped in version 1.5.0. Running `jsftp` on very old Node.js environments will lead to errors.","severity":"breaking","affected_versions":">=1.5.0"},{"fix":"Upgrade `jsftp` to version 1.3.7 or newer. This version introduces proper error generation for simultaneous PASV requests, allowing your application to handle the error gracefully instead of crashing. It is still recommended to sequentialize passive operations where possible.","message":"Prior to version 1.3.7, attempting two simultaneous passive (PASV) requests could result in an `ECONNREFUSED` error and potentially crash the application due to improper error handling.","severity":"gotcha","affected_versions":"<1.3.7"},{"fix":"Update `jsftp` to version 1.3.4 or higher to ensure that `LIST` commands for invalid paths correctly propagate errors to the callback.","message":"In versions prior to 1.3.4, issuing a `LIST` command (directly or via `Ftp.ls`) for a non-existent file or directory would not reliably catch the error or notify the `ls` callback, leading to unhandled promises or stalled operations.","severity":"gotcha","affected_versions":"<1.3.4"},{"fix":"Upgrade `jsftp` to version 1.3.1 or newer. This version fixed the `get` method to correctly abort file retrieval when passive socket errors occur.","message":"Before version 1.3.1, the `get` method could sometimes attempt to retrieve a file even if there was an error obtaining the passive socket, leading to unexpected behavior or resource leaks.","severity":"gotcha","affected_versions":"<1.3.1"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Upgrade to `jsftp` v1.3.7 or higher, which will instead generate an error for this scenario. Prefer sequentializing passive operations or ensure robust error handling for concurrent requests.","cause":"Attempting to perform two passive FTP operations (e.g., file transfers or directory listings) concurrently before `jsftp` version 1.3.7.","error":"ECONNREFUSED on two consecutive PASV operations"},{"fix":"Update `jsftp` to version 1.3.4 or newer to ensure that errors for non-existent paths are correctly passed to the callback.","cause":"Using the `LIST` command or the `Ftp.ls` convenience method on an invalid or non-existent remote path when using `jsftp` versions older than 1.3.4.","error":"LIST command or Ftp.ls callback not fired for non-existent path"},{"fix":"Upgrade `jsftp` to version 1.3.1 or a later version to fix this behavior, ensuring `get` respects passive socket errors.","cause":"A bug in `jsftp` versions prior to 1.3.1 where the `get` method would not properly halt file retrieval even if there was a preceding error in establishing the passive data connection.","error":"File transfer with Ftp.get proceeds despite passive socket error"}],"ecosystem":"npm"}