{"library":"scp","title":"Python SCP Client","description":"The `scp.py` module, currently at version 0.15.0, provides a pure-Python implementation of the SCP1 (Secure Copy Protocol) client. It leverages the `paramiko` library for SSH transport, enabling secure file transfers over SSH connections, mirroring the functionality of the OpenSSH `scp` program. The library is actively maintained but follows an irregular release cadence.","status":"active","version":"0.15.0","language":"en","source_language":"en","source_url":"https://github.com/jbardin/scp.py","tags":["scp","ssh","sftp","paramiko","file transfer","secure copy"],"install":[{"cmd":"pip install scp","lang":"bash","label":"Install `scp`"},{"cmd":"pip install paramiko scp","lang":"bash","label":"Install with core dependency"}],"dependencies":[{"reason":"`scp.py` is built on top of `paramiko` for SSH transport and authentication. It is a mandatory dependency.","package":"paramiko","optional":false}],"imports":[{"note":"This is the primary class for SCP file transfer operations.","symbol":"SCPClient","correct":"from scp import SCPClient"},{"note":"While part of `paramiko`, `SSHClient` is essential for establishing the underlying SSH connection that `SCPClient` uses.","symbol":"SSHClient","correct":"from paramiko import SSHClient"}],"quickstart":{"code":"import os\nfrom paramiko import SSHClient, AutoAddPolicy\nfrom scp import SCPClient\n\n# Configuration from environment variables for security\nHOSTNAME = os.environ.get('SCP_HOSTNAME', 'your_remote_host')\nUSERNAME = os.environ.get('SCP_USERNAME', 'your_username')\nPASSWORD = os.environ.get('SCP_PASSWORD', '') # Use SSH keys in production\n\nlocal_file = 'local_test_file.txt'\nremote_path = '/tmp/remote_test_file.txt'\n\n# Create a dummy local file for the example\nwith open(local_file, 'w') as f:\n    f.write('Hello from scp.py!')\n\nssh = SSHClient()\n# Set policy to auto-add host keys for demo. In production, use ssh.load_system_host_keys() or HostKeys().add().\nssh.set_missing_host_key_policy(AutoAddPolicy()) \n\ntry:\n    # Connect to the remote server\n    ssh.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD, port=22)\n    print(f\"Connected to {HOSTNAME}\")\n\n    # SCPCLient takes a paramiko transport as an argument\n    with SCPClient(ssh.get_transport()) as scp:\n        # Upload a file\n        scp.put(local_file, remote_path)\n        print(f\"Uploaded '{local_file}' to '{remote_path}'\")\n\n        # Download the file back to verify\n        downloaded_file = 'downloaded_test_file.txt'\n        scp.get(remote_path, downloaded_file)\n        print(f\"Downloaded '{remote_path}' to '{downloaded_file}'\")\n\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")\nfinally:\n    ssh.close()\n    print(\"SSH connection closed.\")\n\n# Clean up dummy files\nimport os\nif os.path.exists(local_file):\n    os.remove(local_file)\nif os.path.exists(downloaded_file):\n    os.remove(downloaded_file)","lang":"python","description":"This quickstart demonstrates how to establish an SSH connection using `paramiko.SSHClient` and then use `scp.SCPClient` to upload and download a file. It includes important considerations for host key policy and proper connection closure."},"warnings":[{"fix":"Ensure `paramiko` is installed (`pip install paramiko`) and resolve any underlying `cryptography` installation errors, which might require system-level development packages.","message":"The `scp` library is a thin wrapper around `paramiko`. Therefore, `paramiko` and its dependencies (like `cryptography`, which might require compilation tools) must be correctly installed. Issues with `paramiko` often manifest as `scp` problems.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Prefer `ssh.load_system_host_keys()` or manually add host keys to a `paramiko.HostKeys` object. Implement strict host key checking and handle `paramiko.BadHostKeyException`.","message":"For security, always verify host keys. Using `paramiko.AutoAddPolicy()` in production is dangerous as it makes your client vulnerable to man-in-the-middle attacks.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For new projects or if advanced file transfer features are needed, consider using `paramiko`'s built-in SFTP client (`ssh.open_sftp()`) or higher-level libraries like `Fabric` that might use SFTP.","message":"The underlying SCP1 protocol has known security limitations and is considered deprecated by OpenSSH in favor of SFTP. While `scp.py` implements SCP1, be aware that future changes in OpenSSH servers might affect compatibility or expose vulnerabilities.","severity":"deprecated","affected_versions":"All versions"},{"fix":"Update your progress callback functions to match the 3-argument signature for `progress`, or use the `progress4` parameter if you require the `peername` argument. Review the `CHANGELOG.md` for specific details.","message":"The `progress` callback signature changed in version 0.13.0. It reverted to accepting 3 arguments (`path`, `total_size`, `sent_size`). A new `progress4` parameter was introduced to accept 4 arguments, including `peername`. Code using the 4-argument `progress` callback from pre-0.13.0 versions will break.","severity":"breaking","affected_versions":"<0.13.0 to 0.13.0"},{"fix":"Upgrade to `scp` version 0.13.6 or newer. If upgrading is not possible, ensure source directory paths passed to `put()` do not have trailing slashes if you intend to copy the directory itself rather than its contents.","message":"Prior to version 0.13.6, the `put()` method might have behaved unexpectedly when the source directory path had a trailing slash (e.g., `scp.put('my_dir/', remote_path)`).","severity":"gotcha","affected_versions":"<0.13.6"}],"env_vars":null,"last_verified":"2026-04-06T00:00:00.000Z","next_check":"2026-07-05T00:00:00.000Z"}