notebooklm-py: The Reverse-Engineered NotebookLM That Turns Google’s Research App Into a Programmable Engine

An unofficial Python SDK and CLI exposes hidden exports, bulk automation, and agent-ready workflows by decoding Google’s internal RPC protocol.

9 min read · teng-lin/notebooklm-py

A locked research cabinet is wired into a hidden switchboard while document cards, audio reels, and slide-like sheets spill out from the side. The image explains how notebooklm-py turns a polished closed product into something scriptable, exposing the machinery underneath rather than rebuilding the product from scratch.
The trick is not replacing NotebookLM. It is tapping into the machinery that already powers it.
Key Takeaways

Most unofficial APIs imitate a web app. notebooklm-py does something sharper. It treats NotebookLM as a finished research engine and then teaches Python, CLIs, and even other AIs how to drive it.

That is why the repo matters. It is not simply a convenience wrapper around Google’s research product. It is a translation layer between a polished consumer interface and the undocumented machinery underneath it.

NotebookLM, but callable

The practical leap is easy to miss. With this repo, NotebookLM stops being a browser-only destination and becomes something you can script, schedule, chain, and delegate. The difference shows up in the details: notebooks, sources, chats, artifacts, exports, and bulk automation all become callable operations.

That makes the project useful to two audiences at once. Developers get a Python SDK and CLI. Agents get a skill-shaped interface they can consume without needing to understand the whole product by hand.

How could NotebookLM become fully programmable? A new community project, notebooklm-py, exposes an unofficial Python API for Google’s Google NotebookLM—unlocking automation and workflows that the web UI doesn’t support.

Damien Huzard, PhD, Metadatapp (MAPP) · Damien Huzard, PhD's Post - LinkedIn

The hidden value is not the API, it is the product

The reason this repo lands so well is that it targets a product shape, not a model endpoint. NotebookLM is already opinionated. It knows how to ingest sources, ground answers, and emit artifacts that feel like a research workflow instead of a blank canvas.

That makes the unlock more valuable than raw model access. You are not just calling an LLM. You are borrowing a packaged workflow that already knows how to turn sources into useful outputs.

OptionWhat you start withWhat you must buildWhy it matters
Direct NotebookLM useA polished UIEverything manualGood for one-off research, poor for automation
Official Google AI APIsRaw model accessRetrieval, storage, orchestration, artifact logicFlexible, but you assemble the workflow yourself
LangChain or LlamaIndexA general RAG frameworkProduct shape, UX, export logic, NotebookLM-like behaviorsPowerful, but broad and heavier to finish
notebooklm-pyNotebookLM’s finished workflowOnly your automation around itFastest path to NotebookLM-shaped research pipelines

The point of the table is simple. notebooklm-py is narrower than a general stack, but that narrowness is the feature. It skips the work of rebuilding a product that already knows how to behave like a research assistant.

A close-up hand draws one small request token that expands into nested bracketed arrays, then collapses into a clean output card on the other side. The image explains how the repo translates ugly internal request shapes into usable artifacts, showing the gap between developer intent and Google’s RPC format.
The hard part is not sending a request. It is reshaping it into something Google’s internal protocol accepts, then extracting the real payload on the way back.

The engine room: Google’s internal RPC shape

This is the center of the repo. Google’s NotebookLM backend does not behave like a tidy REST service. The library has to speak in the shape Google expects, which means encoding requests into a nested batchexecute format and decoding responses that arrive wrapped in noise, prefixes, and multiple layers of arrays.

The library’s core job is translation. It turns Python calls into Google’s internal RPC shape, then strips the wrapper off the response and hands back something usable.

At the request level, the code has to build shapes like [[[method_id, json_params, null, "generic"]]]. On the response side, it has to remove anti-XSS prefixes and walk nested structures until the actual payload appears. That is not glamorous work, but it is the entire reason the SDK can exist.

# Conceptual shape, simplified
request = encode_rpc_request(
    method_id="someMethod",
    params={"notebook_id": notebook_id, "source_ids": source_ids},
)

raw = await client.post("/batchexecute", content=request)
payload = decode_rpc_response(raw)

# payload is now usable Python data, not Google's wrapper format

The design choice here is deeper than protocol trivia. By isolating the translation logic, the repo makes a hostile backend feel like a normal dependency. That is what turns reverse engineering into a maintainable tool.

Why the client is split into sub-APIs

The top-level client stays thin on purpose. NotebookLM behavior is divided into domain modules for sources, notebooks, artifacts, chat, and other surfaces. That structure keeps the codebase from collapsing into a single giant wrapper file every time Google adds a new feature.

This is one of the repo’s strongest maturity signals. Reverse-engineered projects usually accrete hacks. This one is organized as if it expects to live through change.

client = NotebookLMClient(auth=auth)

client.sources.import_urls([...])
client.chat.ask("Summarize the common themes")
client.artifacts.download_mind_map(notebook_id)
client.notebooks.list()

# The facade stays small.
# The behavior lives in sub-APIs.

That split also makes the project easier to extend. A new artifact type or source workflow can land in its own module without forcing every other path to know about it.

Authentication is the real long-term tax

Unofficial APIs do not fail politely. Sessions expire. Cookies go stale. CSRF tokens drift. Regional cookie domains can change the shape of login state. This repo treats auth as a first-class system instead of an afterthought.

That matters more than it sounds. A scriptable product is only useful if it can survive the messy middle of long-running automation. Otherwise it is just a demo.

ProblemWhat breaksHow notebooklm-py responds
Session expiryRequests start failing mid-runA refresh callback can reroute into re-authentication
Cookie handlingLogin state is incomplete or region-specificThe auth layer tracks cookies and regional domain edge cases
CSRF driftValid sessions stop being acceptedThe client refreshes the token instead of assuming it remains stable
Browser loginHeadless setup becomes brittlePlaywright-assisted login captures the initial session more reliably

That is the difference between a hack and infrastructure. The project knows the backend is unstable, so it builds systems around the instability instead of pretending it is not there.

Built for agents, not just developers

The most forward-looking move in the repo is not a method. It is the packaging. With SKILL.md and AGENTS.md, notebooklm-py is written so another AI can consume it as a tool.

That changes the mental model. The repo is no longer only a library for humans writing Python. It is also a downstream component in an AI toolchain, something Claude Code or another agent can call when it needs grounded research, artifact generation, or exports.

仕組みはシンプル: 1. notebooklm-pyをインストール(Teng LingがリバースエンジニアリングしたCLI) 2. Claude CodeにSkillとして認識させる 3. ClaudeがNotebookLMに研究をオフロード 4. トークン消費なしで30文書以上を分析可能 GoogleのGeminiが処理するからハルシネーションも少ない。 https://t.co/63GUyvXS6Q

そら ☁️ AgentSkills 自動化オタク📱, sora19ai, 18,928 followers · @sora19ai on X

That is a real shift. The tool stops being just an API consumer and becomes a capability that other AI systems can route work through.

Why this is sturdier than it sounds

The repo’s credibility comes from defensive engineering. Tests use vcrpy cassettes so behavior can be replayed without hammering Google’s servers. Linting, typing, packaging, and integration boundaries are all treated as serious concerns.

That does not make the unofficial API safe. It makes it disciplined. In a world where the backend can change under your feet, discipline is the difference between a useful tool and a maintenance nightmare.

SignalWhat it tells youWhy it matters
vcrpy testsRecorded network interactions are part of the workflowThe team expects unstable external behavior and plans for it
mypy and ruffTyping and linting are enforcedThe codebase is meant to stay readable as it grows
hatchling packagingModern Python build flowRelease mechanics are not improvised
docs on RPC developmentReverse-engineering knowledge is documentedThe hardest part is shared, not hidden in one maintainer’s head

That last point is important. Documenting the RPC shape is a form of resilience. It makes the project easier to keep alive when the product changes.

What notebooklm-py replaces, and what it does not

This repo is not a replacement for every RAG stack. It will not give you the flexibility of a blank-slate retrieval system. It will not replace the broad ecosystem around LangChain or LlamaIndex. It is much more specific than that.

What it does replace is a lot of glue work. If your goal is NotebookLM-shaped research workflows, notebooklm-py gives you a shortcut into an already good product surface. That is a different value proposition from building a system from scratch.

ApproachBest forTrade-off
notebooklm-pyNotebookLM-shaped research automationDepends on an undocumented Google backend
Official Google AI APIsCustom application buildingYou assemble the product behavior yourself
LangChain or LlamaIndexGeneral RAG systemsMore flexibility, more setup, more decisions
Direct NotebookLM UIManual analysis and ad hoc useNo programmable workflow

That is the right way to read the repo. It is not trying to become the universal abstraction. It is trying to make one especially good product programmable.