Feishu2HTML

A powerful Kotlin Multiplatform library and CLI tool to convert Feishu (Lark) documents to beautiful, standalone HTML files.
🌐 Now supports JVM, JS, and Native platforms!
📦 Download Latest Release - Pre-built binaries for macOS, Linux, Windows
📖 View API Documentation - Complete KDoc reference
🚀 Maven Central - Use as library dependency
✨ Features
🎨 Visual Comparison
Feishu2HTML faithfully recreates the original styling and layout. Side-by-side comparison:
| Feishu Online | Local HTML Output |
|---|
 |  |
The generated HTML preserves typography, colors, layout, and all media content with 100% authentic Feishu appearance.
📋 Table of Contents
🚀 Quick Start
Prerequisites
- JVM: JDK 17+, Gradle 8.0+ (or use included wrapper)
- JS: Node.js 16+ (browser not supported)
- Native: Platform toolchain (XCode/GCC/MinGW)
1. Get Feishu App Credentials
- Visit Feishu Open Platform
- Create a self-built app
- Get your
App ID and App Secret
- Add the following permissions to your app:
docx:document - View, comment, and export documents
2. Grant Document Access
Important: You must grant your app access to the documents you want to export:
- Open the Feishu document you want to export
- Click the "Share" button in the top-right corner
- Add your app/bot to the document collaborators
- Grant at least "View" permission
⚠️ Limitation: If your document contains embedded/referenced external documents (e.g., via links or iframe blocks), you must also grant your app access to those external documents. Otherwise, the content may fail to load or appear as broken links.
3. Installation
Download pre-built binaries from GitHub Releases:
- macOS Apple Silicon:
feishu2html-{version}-macosArm64.tar.gz
- macOS Intel:
feishu2html-{version}-macosX64.tar.gz
Or use Maven Central to add as a library dependency.
4. CLI Usage
Using JAR (Recommended):
Download the JVM JAR from GitHub Releases:
curl -L -O https://github.com/yidafu/feishu2html/releases/latest/download/feishu2html-1.0.2-jvm.jar
java -jar feishu2html-1.0.2-jvm.jar <app_id> <app_secret> <document_id>
java -jar feishu2html-1.0.2-jvm.jar <app_id> <app_secret> <doc_id_1> <doc_id_2> <doc_id_3>
java -jar feishu2html-1.0.2-jvm.jar --inline-images --inline-css <app_id> <app_secret> <document_id>
java -jar feishu2html-1.0.2-jvm.jar --hide-unsupported <app_id> <app_secret> <document_id>
java -jar feishu2html-1.0.2-jvm.jar -t fragment --inline-images --inline-css --hide-unsupported <app_id> <app_secret> <document_id>
CLI Options:
Options:
-t,
-h,
Using Gradle (from source):
git clone https://github.com/yidafu/feishu2html.git
cd feishu2html
./gradlew runJvm --args="<app_id> <app_secret> <document_id>"
./gradlew runJvm --args="--inline-images --inline-css <app_id> <app_secret> <document_id>"
Example:
java -jar feishu2html-1.0.2-jvm.jar cli_a1234567890abcde your_app_secret_here doxcnABC123XYZ456
Output files will be saved to ./output/ directory by default.
5. Library Usage
Add to Your Project
Kotlin Multiplatform Project:
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("dev.yidafu.feishu2html:feishu2html:1.0.2")
}
}
}
}
JVM-only Project:
dependencies {
implementation("dev.yidafu.feishu2html:feishu2html-jvm:1.0.2")
}
JS Project:
dependencies {
implementation("dev.yidafu.feishu2html:feishu2html-js:1.0.2")
}
Basic Example
import dev.yidafu.feishu2html.Feishu2Html
import dev.yidafu.feishu2html.Feishu2HtmlOptions
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val options = Feishu2HtmlOptions(
appId = "your_app_id",
appSecret = "your_app_secret"
)
Feishu2Html(options).use { converter ->
converter.export("doxcnABC123XYZ456")
println("Export completed successfully!")
}
}
Advanced Example with Custom Options
Available Options:
6. CSS Styling Options
Using Official Feishu Styles (Default)
By default, exported HTML uses an optimized version extracted from official Feishu CSS:
val options = Feishu2HtmlOptions(
appId = "your_app_id",
appSecret = "your_app_secret",
externalCss = true,
cssFileName = "feishu-style-optimized.css"
)
Feishu2Html(options).use { converter ->
converter.export("document_id")
}
Why Optimized CSS? 98.4% smaller (16KB vs 1MB), faster load times, only needed selectors, 100% authentic appearance.
Inline CSS Mode
Use inline CSS for single-file portability (no separate CSS file):
val options = Feishu2HtmlOptions(
appId = "your_app_id",
appSecret = "your_app_secret",
externalCss = false
)
Custom CSS Styling
Override with your own CSS (requires inline mode):
val customCss = """
.protyle-wysiwyg { font-family: "Inter", sans-serif; }
.heading-h1 { color: #2c3e50; border-bottom: 3px solid #3498db; }
/* Add more custom styles... */
""".trimIndent()
val options = Feishu2HtmlOptions(
appId = "your_app_id",
appSecret = "your_app_secret",
externalCss = false,
customCss = customCss
)
📚 Usage Guides
Detailed platform-specific usage guides:
- JVM Usage Guide - Complete guide for JVM platform (CLI & Library)
- Node.js Usage Guide - CommonJS setup and usage
- - Native macOS executable (ARM64 & Intel)
🌐 Multiplatform Support
Feishu2HTML is built with Kotlin Multiplatform, enabling it to run on multiple platforms from a single codebase.
Supported Platforms
Platform-Specific Notes
- JVM: Full support including CLI tool, Logback logging, and complete file I/O
- JS (Node.js): File system via Node.js fs module, Ktor client, browser not supported
- Native: POSIX file I/O, platform-specific HTTP engines (Darwin/Curl)
Build Targets
Build for specific platforms:
./gradlew compileKotlinJvm
./gradlew jvmJar
./gradlew compileKotlinJs
./gradlew jsJar
./gradlew compileKotlinMacosArm64
./gradlew build
Platform-Specific Usage
All platforms use the same API (see Library Usage for examples):
- JVM: Use
runBlocking coroutine scope
- JS (Node.js): Use
GlobalScope.promise for async execution
- Native: Use
runBlocking coroutine scope
🔍 Getting Document ID
The document ID can be extracted from the Feishu document URL:
https:
└─────────────────┘
Document ID
For example:
- URL:
https://company.feishu.cn/docx/TPDddjY5foJZ8axlf9fctf2Wnse
- Document ID:
TPDddjY5foJZ8axlf9fctf2Wnse
🔧 Troubleshooting
1. Token Acquisition Failure
Error: Failed to get token: app access token invalid
Solutions:
- Verify
app_id and app_secret are correct
- Ensure the app is enabled and published
- Check app permissions are configured
2. Document Access Failure
Error: Failed to get document content: no permission
Solutions:
- Confirm app has required permissions
- Ensure document is accessible to the app
- Try adding the app to document collaborators
3. Image Download Failure
Solutions:
- Check network connection
- Confirm app has
drive:drive permission
- Some legacy documents may have API limitations
⚠️ Known Limitations
1. External Document References
When a Feishu document contains references to other documents (e.g., embedded documents, links to other docs), you must grant your app access to all referenced documents as well. The tool cannot automatically propagate permissions.
Workaround: Manually share each referenced document with your app before exporting.
2. Real-time Collaboration Content
Content from real-time collaboration features (e.g., comments, suggestions) is not included in the export.
3. Unsupported Block Types
Some advanced block types are not yet supported (ISV, Mindnote, Sheet, Task, OKR, Wiki Catalog, Agenda, Link Preview, etc.). By default, these will display a placeholder message for debugging purposes.
Solution: Use the --hide-unsupported CLI option or set showUnsupportedBlocks = false in library usage to hide these warnings for cleaner output.
java -jar feishu2html.jar --hide-unsupported <app_id> <app_secret> <document_id>
val options = Feishu2HtmlOptions(
appId = "your_app_id",
appSecret = "your_app_secret",
showUnsupportedBlocks = false
)
See the Supported Block Types table for a complete list.
4. API Rate Limiting
The Feishu API has rate limits. The tool includes built-in rate limiting (QPS=2) to avoid exceeding limits, but very large documents may take time to process.
📖 API Documentation & References
API Documentation
Complete API documentation is automatically generated and published to GitHub Pages:
🔗 View Online API Documentation
The documentation is automatically updated on every push to the main branch.
Platform-Specific Guides
- JVM Usage Guide - Detailed JVM platform guide
- Node.js Usage Guide - Node.js / JavaScript guide
- macOS Usage Guide - Native macOS executable guide
- Linux Usage Guide - Native Linux executable guide
- Windows Usage Guide - Native Windows executable guide
Feishu API References
📊 Supported Block Types
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for architecture, coding standards, and PR guidelines.
🙏 Acknowledgments
This project was inspired by feishu2md.
Made with ❤️ by the Feishu2HTML contributors
20:53:59.100 [main] INFO dev.yidafu.feishu2html.api.FeishuAuthService -- Requesting new tenant_access_token
20:53:59.100 [main] DEBUG dev.yidafu.feishu2html.api.FeishuAuthService -- App ID: cli_a8790687b4bdd01c
20:53:59.101 [main] DEBUG dev.yidafu.feishu2html.api.FeishuAuthService -- App Secret: 3sXNpzmX4ErVg07gNMOgdMkQn2usPg
20:54:47.596 [main] INFO dev.yidafu.feishu2html.api.FeishuAuthService -- Requesting new tenant_access_token
20:54:47.596 [main] DEBUG dev.yidafu.feishu2html.api.FeishuAuthService -- App ID: cli_a8790687b4bdd01c
20:54:47.596 [main] DEBUG dev.yidafu.feishu2html.api.FeishuAuthService -- App Secret: 3sxXNpzmX4ErVg07gNMOgdMkQn2usPgq