
Client SDK for Proton Drive: SRP + TOTP login, session persistence and refresh, file/folder operations, encrypted upload/download with block-hash and manifest-signature verification, OpenPGP via PGPainless, no native binaries.
Proton Drive client SDK implemented for Kotlin Multiplatform. An unofficial port of the proton-sdk TypeScript client, using PGPainless for OpenPGP — no native binaries or JNI.
This is a third-party, unofficial project — not affiliated with, endorsed by, or supported by Proton. Per Proton's SDK usage guidelines, this kind of integration is only sanctioned for personal, non-commercial use.
Features:
What's missing:
moveNode/copyNode are files-only)Add the repository:
repositories {
mavenCentral()
}Put in your dependencies block:
implementation("dev.carlsen.protondrive:protondrive:1.0.0-beta01")// Initialize the SDK - appVersion identifies your app to Proton's API
val sdk = ProtonDriveSdk(
appVersion = "external-drive-myapp@1.0.0",
onSessionChanged = { session -> /* persist it - the SDK never touches disk */ },
)
// Log in to your Proton account
val loginResult = sdk.login("username", "password")
if (loginResult.twoFactorRequired) {
sdk.submitTwoFactorCode("123456")
}
val account = sdk.finishLogin("password")!!
// ...or resume a previously persisted session instead
// val account = sdk.restoreSession(savedSession)
// Access your files
val drive = account.driveClient
val root = drive.getMyFilesRoot()
val children = drive.listChildren(root)
// Download a file
val file = children.first { it.name == "example.pdf" }
SystemFileSystem.sink(Path("download.pdf")).buffered().use { sink ->
drive.downloadFile(file, parent = root, sink = sink) { downloadedBytes ->
println("Downloaded $downloadedBytes bytes")
}
}
// Upload a file
SystemFileSystem.source(Path("documents/report.pdf")).buffered().use { source ->
drive.uploadFile(
parent = root,
name = "uploaded-report.pdf",
source = source,
mediaType = "application/pdf",
)
}
// Create, rename, move, trash
val folder = drive.createFolder(root, "My New Folder")
drive.renameNode(file, parent = root, newName = "renamed.pdf")
drive.moveNode(file, oldParent = root, newParent = folder)
drive.trashNode(file)
// Logout when done
sdk.logout()The cli module is a runnable desktop CLI with an interactive file browser, useful for trying the SDK against a real account:
./gradlew :cli:installDist
./cli/build/install/cli/bin/cli./gradlew :sdk:jvmTestAll tests are self-contained (fake HTTP clients, a from-scratch SRP server) — none talk to the real Proton API.
Proton Drive client SDK implemented for Kotlin Multiplatform. An unofficial port of the proton-sdk TypeScript client, using PGPainless for OpenPGP — no native binaries or JNI.
This is a third-party, unofficial project — not affiliated with, endorsed by, or supported by Proton. Per Proton's SDK usage guidelines, this kind of integration is only sanctioned for personal, non-commercial use.
Features:
What's missing:
moveNode/copyNode are files-only)Add the repository:
repositories {
mavenCentral()
}Put in your dependencies block:
implementation("dev.carlsen.protondrive:protondrive:1.0.0-beta01")// Initialize the SDK - appVersion identifies your app to Proton's API
val sdk = ProtonDriveSdk(
appVersion = "external-drive-myapp@1.0.0",
onSessionChanged = { session -> /* persist it - the SDK never touches disk */ },
)
// Log in to your Proton account
val loginResult = sdk.login("username", "password")
if (loginResult.twoFactorRequired) {
sdk.submitTwoFactorCode("123456")
}
val account = sdk.finishLogin("password")!!
// ...or resume a previously persisted session instead
// val account = sdk.restoreSession(savedSession)
// Access your files
val drive = account.driveClient
val root = drive.getMyFilesRoot()
val children = drive.listChildren(root)
// Download a file
val file = children.first { it.name == "example.pdf" }
SystemFileSystem.sink(Path("download.pdf")).buffered().use { sink ->
drive.downloadFile(file, parent = root, sink = sink) { downloadedBytes ->
println("Downloaded $downloadedBytes bytes")
}
}
// Upload a file
SystemFileSystem.source(Path("documents/report.pdf")).buffered().use { source ->
drive.uploadFile(
parent = root,
name = "uploaded-report.pdf",
source = source,
mediaType = "application/pdf",
)
}
// Create, rename, move, trash
val folder = drive.createFolder(root, "My New Folder")
drive.renameNode(file, parent = root, newName = "renamed.pdf")
drive.moveNode(file, oldParent = root, newParent = folder)
drive.trashNode(file)
// Logout when done
sdk.logout()The cli module is a runnable desktop CLI with an interactive file browser, useful for trying the SDK against a real account:
./gradlew :cli:installDist
./cli/build/install/cli/bin/cli./gradlew :sdk:jvmTestAll tests are self-contained (fake HTTP clients, a from-scratch SRP server) — none talk to the real Proton API.