NotebookLM Skill
Provides full programmatic access to Google NotebookLM via the unofficial notebooklm-py library. Supports Python API and CLI — use the Python API for complex or multi-step workflows, CLI for quick one-off tasks.
Prerequisites
pip install "notebooklm-py[browser]"
playwright install chromium
# First-time auth (opens browser)
notebooklm login
Auth via env variable (CI/CD, no browser):
export NOTEBOOKLM_AUTH_JSON='{"cookies": [...]}'
Read references/auth.md for detailed authentication setup.
Quick Start Pattern
import asyncio
from notebooklm import NotebookLMClient
async def main():
async with await NotebookLMClient.from_storage() as client:
nb = await client.notebooks.create("My Research")
await client.sources.add_url(nb.id, "https://example.com/article", wait=True)
result = await client.chat.ask(nb.id, "Summarize the main points")
print(result.answer)
asyncio.run(main())
API Reference Summary
Client Structure
NotebookLMClient
├── .notebooks → NotebooksAPI
├── .sources → SourcesAPI
├── .artifacts → ArtifactsAPI
├── .chat → ChatAPI
├── .research → ResearchAPI
├── .notes → NotesAPI
└── .sharing → SharingAPI
Notebooks (client.notebooks)
| Method |
Description |
list() |
List all notebooks |
create(title) |
Create new notebook → Notebook |
get(notebook_id) |
Get notebook details |
delete(notebook_id) |
Delete notebook |
rename(notebook_id, new_title) |
Rename notebook |
get_description(notebook_id) |
Get AI summary + suggested topics |
Sources (client.sources)
| Method |
Description |
add_url(nb_id, url, wait=True) |
Add URL/YouTube source |
add_file(nb_id, path, wait=True) |
Add local file (PDF, txt, md, docx, etc.) |
add_text(nb_id, text, title, wait=True) |
Add pasted text |
add_drive(nb_id, drive_id, title) |
Add Google Drive document |
list(nb_id) |
List all sources |
get(nb_id, source_id) |
Get source details |
fulltext(nb_id, source_id) |
Get indexed text content |
refresh(nb_id, source_id) |
Refresh URL source |
delete(nb_id, source_id) |
Delete source |
Chat (client.chat)
| Method |
Description |
ask(nb_id, question, source_ids=None) |
Ask a question → ChatResult |
history(nb_id) |
Get conversation history |
configure(nb_id, mode=None, persona=None) |
Set chat mode/persona |
Artifacts — Generate (client.artifacts)
All generate methods return a GenerationStatus with task_id. Use wait_for_completion() to poll until done.
| Method |
Key Options |
Download Method |
generate_audio(nb_id, instructions, format, length, language) |
format: deep-dive/brief/critique/debate, length: short/default/long |
download_audio(nb_id, path) |
generate_video(nb_id, instructions, format, style) |
style: classic/whiteboard/kawaii/anime/watercolor/... |
download_video(nb_id, path) |
generate_quiz(nb_id, difficulty, quantity) |
difficulty: easy/medium/hard |
download_quiz(nb_id, path, output_format) |
generate_flashcards(nb_id, difficulty, quantity) |
— |
download_flashcards(nb_id, path, output_format) |
generate_slide_deck(nb_id, instructions, format) |
format: detailed/presenter |
download_slide_deck(nb_id, path) — PDF or PPTX |
generate_infographic(nb_id, orientation, detail) |
orientation: landscape/portrait/square |
download_infographic(nb_id, path) |
generate_report(nb_id, format, instructions) |
format: briefing-doc/study-guide/blog-post/custom |
download_report(nb_id, path) |
generate_data_table(nb_id, instructions) |
— |
download_data_table(nb_id, path) |
generate_mind_map(nb_id) |
Sync, no wait needed |
download_mind_map(nb_id, path) |
Wait pattern:
status = await client.artifacts.generate_audio(nb_id, instructions="Focus on key facts")
final = await client.artifacts.wait_for_completion(nb_id, status.task_id, timeout=300)
if final.is_complete:
await client.artifacts.download_audio(nb_id, "./podcast.mp3")
Research (client.research)
# Start web research
research = await client.research.start(nb_id, "quantum computing trends", source="web", mode="deep")
# Poll until complete
status = await client.research.poll(nb_id)
# Import discovered sources
await client.research.import_sources(nb_id, task_id, sources[:10])
CLI Quick Reference
# Session
notebooklm login
notebooklm use <notebook_id>
notebooklm status
# Notebooks
notebooklm list
notebooklm create "My Notebook"
notebooklm delete <id>
notebooklm rename "New Title"
# Sources
notebooklm source add "https://example.com"
notebooklm source add ./paper.pdf
notebooklm source add-research "AI trends 2025" --mode deep --import-all
notebooklm source list
# Chat
notebooklm ask "What are the key themes?"
# Generate (--wait blocks until done)
notebooklm generate audio "make it engaging" --wait
notebooklm generate video --style whiteboard --wait
notebooklm generate quiz --difficulty hard --wait
notebooklm generate flashcards --quantity more --wait
notebooklm generate slide-deck --wait
notebooklm generate infographic --orientation portrait --wait
notebooklm generate report --format study-guide --wait
notebooklm generate mind-map
# Download
notebooklm download audio ./podcast.mp3
notebooklm download video ./overview.mp4
notebooklm download quiz --format json ./quiz.json
notebooklm download flashcards --format markdown ./cards.md
notebooklm download slide-deck ./slides.pdf
notebooklm download mind-map ./mindmap.json
notebooklm download data-table ./data.csv
Common Workflows
Research → Podcast
See references/workflows.md for the full pattern.
Bulk Source Import
urls = ["https://...", "https://...", ...]
for url in urls:
await client.sources.add_url(nb_id, url, wait=False)
await asyncio.sleep(1) # Rate limiting
Quiz Generation + JSON Export
status = await client.artifacts.generate_quiz(nb_id, difficulty="hard")
final = await client.artifacts.wait_for_completion(nb_id, status.task_id)
await client.artifacts.download_quiz(nb_id, "quiz.json", output_format="json")
Error Handling
from notebooklm import RPCError
try:
result = await client.notebooks.create("Test")
except RPCError as e:
# Session expired → re-run `notebooklm login`
# Rate limited → wait and retry
print(f"Error: {e}")
Common issues:
RPCError auth failure → re-run notebooklm login or call await client.refresh_auth()
- Rate limits → add
await asyncio.sleep(2) between bulk operations
- Source not ready → use
wait=True in add_url() / add_file()
Reference Files
references/auth.md — Detailed auth setup, CI/CD, environment variables
references/workflows.md — Complete workflow examples (research→podcast, bulk import, etc.)
references/artifact-options.md — All generation options, formats, and styles
1---2name: notebook-lm3description: Automate Google NotebookLM via the notebooklm-py Python library. Use this skill whenever the user wants to create, manage, or delete NotebookLM notebooks; add sources (URLs, YouTube, PDFs, files, text, Google Drive) to a notebook; ask questions or chat with notebook content; generate content like Audio Overview (podcast), Video Overview, Quiz, Flashcards, Slide Deck, Infographic, Report, Data Table, or Mind Map; download generated artifacts (MP3, MP4, PDF, PNG, CSV, JSON, Markdown); run web/Drive research and auto-import results; manage sharing, notes, and source full-text extraction; or automate any NotebookLM workflow programmatically. Trigger this skill for ANY request involving NotebookLM, notebooklm-py, Google NotebookLM automation, podcast/audio overview generation from notes, or bulk research pipelines.4---56# NotebookLM Skill78Provides full programmatic access to Google NotebookLM via the unofficial `notebooklm-py` library. Supports Python API and CLI — use the Python API for complex or multi-step workflows, CLI for quick one-off tasks.910## Prerequisites1112```bash13pip install "notebooklm-py[browser]"14playwright install chromium1516# First-time auth (opens browser)17notebooklm login18```1920**Auth via env variable (CI/CD, no browser):**21```bash22export NOTEBOOKLM_AUTH_JSON='{"cookies": [...]}'23```2425Read `references/auth.md` for detailed authentication setup.2627## Quick Start Pattern2829```python30import asyncio31from notebooklm import NotebookLMClient3233async def main():34 async with await NotebookLMClient.from_storage() as client:35 nb = await client.notebooks.create("My Research")36 await client.sources.add_url(nb.id, "https://example.com/article", wait=True)37 result = await client.chat.ask(nb.id, "Summarize the main points")38 print(result.answer)3940asyncio.run(main())41```4243## API Reference Summary4445### Client Structure46```47NotebookLMClient48├── .notebooks → NotebooksAPI49├── .sources → SourcesAPI50├── .artifacts → ArtifactsAPI51├── .chat → ChatAPI52├── .research → ResearchAPI53├── .notes → NotesAPI54└── .sharing → SharingAPI55```5657### Notebooks (`client.notebooks`)58| Method | Description |59|--------|-------------|60| `list()` | List all notebooks |61| `create(title)` | Create new notebook → `Notebook` |62| `get(notebook_id)` | Get notebook details |63| `delete(notebook_id)` | Delete notebook |64| `rename(notebook_id, new_title)` | Rename notebook |65| `get_description(notebook_id)` | Get AI summary + suggested topics |6667### Sources (`client.sources`)68| Method | Description |69|--------|-------------|70| `add_url(nb_id, url, wait=True)` | Add URL/YouTube source |71| `add_file(nb_id, path, wait=True)` | Add local file (PDF, txt, md, docx, etc.) |72| `add_text(nb_id, text, title, wait=True)` | Add pasted text |73| `add_drive(nb_id, drive_id, title)` | Add Google Drive document |74| `list(nb_id)` | List all sources |75| `get(nb_id, source_id)` | Get source details |76| `fulltext(nb_id, source_id)` | Get indexed text content |77| `refresh(nb_id, source_id)` | Refresh URL source |78| `delete(nb_id, source_id)` | Delete source |7980### Chat (`client.chat`)81| Method | Description |82|--------|-------------|83| `ask(nb_id, question, source_ids=None)` | Ask a question → `ChatResult` |84| `history(nb_id)` | Get conversation history |85| `configure(nb_id, mode=None, persona=None)` | Set chat mode/persona |8687### Artifacts — Generate (`client.artifacts`)8889All generate methods return a `GenerationStatus` with `task_id`. Use `wait_for_completion()` to poll until done.9091| Method | Key Options | Download Method |92|--------|-------------|-----------------|93| `generate_audio(nb_id, instructions, format, length, language)` | format: `deep-dive/brief/critique/debate`, length: `short/default/long` | `download_audio(nb_id, path)` |94| `generate_video(nb_id, instructions, format, style)` | style: `classic/whiteboard/kawaii/anime/watercolor/...` | `download_video(nb_id, path)` |95| `generate_quiz(nb_id, difficulty, quantity)` | difficulty: `easy/medium/hard` | `download_quiz(nb_id, path, output_format)` |96| `generate_flashcards(nb_id, difficulty, quantity)` | — | `download_flashcards(nb_id, path, output_format)` |97| `generate_slide_deck(nb_id, instructions, format)` | format: `detailed/presenter` | `download_slide_deck(nb_id, path)` — PDF or PPTX |98| `generate_infographic(nb_id, orientation, detail)` | orientation: `landscape/portrait/square` | `download_infographic(nb_id, path)` |99| `generate_report(nb_id, format, instructions)` | format: `briefing-doc/study-guide/blog-post/custom` | `download_report(nb_id, path)` |100| `generate_data_table(nb_id, instructions)` | — | `download_data_table(nb_id, path)` |101| `generate_mind_map(nb_id)` | Sync, no wait needed | `download_mind_map(nb_id, path)` |102103**Wait pattern:**104```python105status = await client.artifacts.generate_audio(nb_id, instructions="Focus on key facts")106final = await client.artifacts.wait_for_completion(nb_id, status.task_id, timeout=300)107if final.is_complete:108 await client.artifacts.download_audio(nb_id, "./podcast.mp3")109```110111### Research (`client.research`)112```python113# Start web research114research = await client.research.start(nb_id, "quantum computing trends", source="web", mode="deep")115# Poll until complete116status = await client.research.poll(nb_id)117# Import discovered sources118await client.research.import_sources(nb_id, task_id, sources[:10])119```120121## CLI Quick Reference122123```bash124# Session125notebooklm login126notebooklm use <notebook_id>127notebooklm status128129# Notebooks130notebooklm list131notebooklm create "My Notebook"132notebooklm delete <id>133notebooklm rename "New Title"134135# Sources136notebooklm source add "https://example.com"137notebooklm source add ./paper.pdf138notebooklm source add-research "AI trends 2025" --mode deep --import-all139notebooklm source list140141# Chat142notebooklm ask "What are the key themes?"143144# Generate (--wait blocks until done)145notebooklm generate audio "make it engaging" --wait146notebooklm generate video --style whiteboard --wait147notebooklm generate quiz --difficulty hard --wait148notebooklm generate flashcards --quantity more --wait149notebooklm generate slide-deck --wait150notebooklm generate infographic --orientation portrait --wait151notebooklm generate report --format study-guide --wait152notebooklm generate mind-map153154# Download155notebooklm download audio ./podcast.mp3156notebooklm download video ./overview.mp4157notebooklm download quiz --format json ./quiz.json158notebooklm download flashcards --format markdown ./cards.md159notebooklm download slide-deck ./slides.pdf160notebooklm download mind-map ./mindmap.json161notebooklm download data-table ./data.csv162```163164## Common Workflows165166### Research → Podcast167See `references/workflows.md` for the full pattern.168169### Bulk Source Import170```python171urls = ["https://...", "https://...", ...]172for url in urls:173 await client.sources.add_url(nb_id, url, wait=False)174 await asyncio.sleep(1) # Rate limiting175```176177### Quiz Generation + JSON Export178```python179status = await client.artifacts.generate_quiz(nb_id, difficulty="hard")180final = await client.artifacts.wait_for_completion(nb_id, status.task_id)181await client.artifacts.download_quiz(nb_id, "quiz.json", output_format="json")182```183184## Error Handling185186```python187from notebooklm import RPCError188189try:190 result = await client.notebooks.create("Test")191except RPCError as e:192 # Session expired → re-run `notebooklm login`193 # Rate limited → wait and retry194 print(f"Error: {e}")195```196197**Common issues:**198- `RPCError` auth failure → re-run `notebooklm login` or call `await client.refresh_auth()`199- Rate limits → add `await asyncio.sleep(2)` between bulk operations200- Source not ready → use `wait=True` in `add_url()` / `add_file()`201202## Reference Files203204- `references/auth.md` — Detailed auth setup, CI/CD, environment variables205- `references/workflows.md` — Complete workflow examples (research→podcast, bulk import, etc.)206- `references/artifact-options.md` — All generation options, formats, and styles