W3docs

ftp_pasv()

The ftp_pasv() function is a built-in PHP function that enables passive mode for the FTP connection. In this article, we'll discuss the function in detail and

The PHP ftp_pasv() Function

The ftp_pasv() function turns passive mode on or off for an open FTP connection. Passive mode controls which side opens the data channel during a transfer, and getting it right is the single most common fix when FTP downloads and directory listings hang or time out. This chapter explains what passive mode is, when you need it, and how to call ftp_pasv() correctly in a real transfer script.

Active vs. passive mode

FTP uses two separate channels: a command channel (where you send LIST, RETR, etc.) and a data channel (where the actual file bytes or listing flow). The two modes differ only in who opens the data channel:

  • Active mode (default in the protocol): the server opens the data connection back to the client. If the client sits behind a firewall or NAT router, that inbound connection is usually blocked, so the transfer stalls.
  • Passive mode: the client opens both channels to the server. Because the client only ever makes outbound connections, it works through almost any firewall or NAT setup.

That is why passive mode is the safe default for most modern scripts: clients are nearly always behind NAT, while servers are reachable on a public address.

Syntax

ftp_pasv(FTP\Connection $ftp, bool $passive): bool
  • $ftp — the FTP connection returned by ftp_connect(). As of PHP 8.1 this is an FTP\Connection object; in PHP 8.0 and earlier it was a resource. Existing code keeps working either way.
  • $passivetrue to enable passive mode, false to switch back to active mode.

The function returns true on success and false on failure.

Order matters: call ftp_pasv() after ftp_login() and before any transfer such as ftp_get(), ftp_put(), or ftp_nlist(). Calling it before login fails because passive mode is negotiated within an authenticated session.

A complete transfer in passive mode

The example below connects, logs in, switches to passive mode, downloads a file, and cleans up. Every step checks its return value so failures are reported instead of silently ignored.

<?php

// 1. Connect to the FTP server (30-second timeout)
$ftp = ftp_connect('ftp.example.com', 21, 30);
if (!$ftp) {
    die("Could not connect to the FTP server.\n");
}

// 2. Authenticate
if (!ftp_login($ftp, 'username', 'password')) {
    ftp_close($ftp);
    die("FTP login failed.\n");
}

// 3. Switch to passive mode — must come after login, before any transfer
if (!ftp_pasv($ftp, true)) {
    ftp_close($ftp);
    die("Could not switch to passive mode.\n");
}

// 4. Download a file now that the data channel will be client-initiated
if (ftp_get($ftp, 'local-copy.txt', 'remote/report.txt', FTP_BINARY)) {
    echo "File downloaded successfully.\n";
} else {
    echo "File download failed.\n";
}

// 5. Always close the connection
ftp_close($ftp);

Without the ftp_pasv($ftp, true) line, step 4 would frequently hang behind a NAT router because the server could not open the inbound data connection.

Handling failures

ftp_pasv() returns false when the server refuses the mode change or the connection is no longer valid. Always check the return value before attempting a transfer, and use ftp_close() to release the connection on every exit path:

<?php

if (!ftp_pasv($ftp, true)) {
    echo "Failed to enable passive mode on the remote server.\n";
    ftp_close($ftp);
    return; // stop before attempting a transfer that would stall
}

When to use active mode instead

Passive mode fits most clients, but a few situations call for active mode (ftp_pasv($ftp, false)):

  • The server's passive-port range is firewalled, so passive data connections are refused while active ones succeed.
  • You are connecting from a host with a public IP and no inbound restrictions, talking to a server that only permits active transfers.

If a transfer hangs, flipping the mode is the first thing to try — many "FTP is broken" reports are simply the wrong mode for the network.

Conclusion

ftp_pasv() decides whether the client or the server opens the FTP data channel. Enable it (true) for clients behind firewalls or NAT — which is most of the time — and call it right after ftp_login() and before any transfer. Checking its return value and closing the connection with ftp_close() keeps your FTP scripts reliable across different network setups.

Practice

Practice
What does the pasv() function do in FTP using PHP?
What does the pasv() function do in FTP using PHP?
Was this page helpful?