How to Handle Source Freshness Checking and Refresh Operations in NotebookLM-Py
Use the check_freshness() method to query the backend for staleness, then call refresh() to trigger re-crawling when needed.
The notebooklm-py library provides a Pythonic interface to Google's NotebookLM service, including robust tools to handle source freshness checking and refresh operations. Whether you're managing URLs, Google Drive files, or YouTube videos, the SDK abstracts the underlying RPC complexity into simple boolean checks and explicit refresh commands.
Understanding Source Freshness in NotebookLM-Py
NotebookLM-Py treats a source as fresh until the backend reports that its content has changed. The freshness state depends on the source type—URLs, Drive documents, and videos each return different response structures from the NotebookLM API.
The SDK normalizes these idiosyncrasies in src/notebooklm/_sources.py, converting complex nested lists and null values into a straightforward boolean: True means fresh, False means stale and requires a refresh.
Checking Source Freshness Programmatically
To verify whether a source needs updating, use the check_freshness method on the Sources manager. This method constructs an RPC payload and interprets the backend's heterogeneous response formats.
from notebooklm import NotebookLMClient
async def is_source_fresh(notebook_id: str, source_id: str) -> bool:
async with await NotebookLMClient.from_storage() as client:
# Resolve partial IDs to full UUIDs
nb_id = await client.notebooks.resolve_id(notebook_id)
src_id = await client.sources.resolve_id(nb_id, source_id)
# Check freshness
fresh = await client.sources.check_freshness(nb_id, src_id)
return fresh
The check_freshness Method Implementation
In src/notebooklm/_sources.py (lines 90-124), the check_freshness method builds the RPC payload as params = [None, [source_id], [2]] and calls RPCMethod.CHECK_SOURCE_FRESHNESS (ID yR9Yof).
The backend returns varying structures depending on source type:
[]→ fresh (URL sources)[[null, true, [source_id]]]→ fresh (Drive sources)True→ fresh (generic)False→ stale
The method normalizes these into a single boolean by inspecting the response list length, nested values, or direct boolean returns (lines 106-124).
Refreshing Stale Sources
When check_freshness returns False, trigger a backend re-crawl using the refresh method. This operation requests the NotebookLM service to update the indexed text for the specified source.
async def refresh_if_stale(client, notebook_id: str, source_id: str):
is_fresh = await client.sources.check_freshness(notebook_id, source_id)
if not is_fresh:
print("Source is stale – triggering refresh")
success = await client.sources.refresh(notebook_id, source_id)
if success:
print("Refresh request accepted")
# Optionally wait for processing to complete
await client.sources.wait(notebook_id, source_id, timeout=180)
else:
print("Source is already fresh")
The refresh Method Implementation
Located in src/notebooklm/_sources.py (lines 71-88), the refresh method uses the same three-element parameter format [None, [source_id], [2]] but invokes RPCMethod.REFRESH_SOURCE (ID FLmJqe).
Unlike check_freshness, this call does not return data from the backend; the method simply returns True if the RPC request was accepted, indicating that the re-crawl has been queued.
CLI Commands for Freshness and Refresh Operations
The command-line interface in src/notebooklm/cli/source.py provides direct access to these operations without writing Python code.
Checking Freshness via CLI
Use notebooklm source stale to check freshness from the shell:
notebooklm source stale <SOURCE_ID>
This command:
- Resolves partial IDs to full UUIDs using
resolve_source_id - Runs
client.sources.check_freshness - Prints a green "fresh" or yellow "stale" message
- Exits with code 1 for fresh sources and code 0 for stale sources (lines 618-654 in
source.py)
This exit code inversion is designed for shell scripting: a "true" (0) exit status means action is required (stale), allowing constructions like:
if notebooklm source stale "$SRC_ID"; then
notebooklm source refresh "$SRC_ID"
fi
Triggering Refresh via CLI
Use notebooklm source refresh to trigger re-crawling:
notebooklm source refresh <SOURCE_ID>
This command (lines 20-52 in source.py):
- Resolves the source ID
- Invokes
client.sources.refresh - Reports success by printing the source ID or title
- Returns
Truewhen the backend accepts the request
Complete Workflow Example
Combine freshness checking, conditional refreshing, and waiting for processing in a single script:
import asyncio
from notebooklm import NotebookLMClient
async def ensure_fresh_source(notebook_id: str, source_id: str):
async with await NotebookLMClient.from_storage() as client:
# Resolve IDs
nb = await client.notebooks.resolve_id(notebook_id)
src = await client.sources.resolve_id(nb, source_id)
# Check freshness
if await client.sources.check_freshness(nb, src):
print(f"Source {src} is fresh")
return
# Refresh if stale
print(f"Source {src} is stale, refreshing...")
await client.sources.refresh(nb, src)
# Wait for completion
await client.sources.wait(nb, src, timeout=300)
print("Source refreshed and ready")
# Run
asyncio.run(ensure_fresh_source("nb-abc123", "src-xyz789"))
Summary
- Freshness checking uses
RPCMethod.CHECK_SOURCE_FRESHNESS(IDyR9Yof) insrc/notebooklm/_sources.pyto return a normalized boolean indicating whether the source content has changed. - Refresh operations trigger backend re-crawling via
RPCMethod.REFRESH_SOURCE(IDFLmJqe), accepting the same[None, [source_id], [2]]payload format. - CLI integration provides
notebooklm source stale(exit code 0 for stale, 1 for fresh) andnotebooklm source refreshfor shell scripting. - Response normalization handles heterogeneous backend formats—empty lists for URLs, nested structures for Drive files, and plain booleans—converting all to simple
True/Falsevalues.
Frequently Asked Questions
How does NotebookLM-Py determine if a source is fresh or stale?
NotebookLM-Py queries the backend using RPCMethod.CHECK_SOURCE_FRESHNESS (ID yR9Yof) with a payload of [None, [source_id], [2]]. The backend returns varying structures depending on source type—empty lists for fresh URLs, nested [null, true, [source_id]] arrays for fresh Drive files, or plain booleans. The SDK normalizes these into a single boolean where True indicates fresh content and False indicates stale content requiring a refresh.
What is the difference between check_freshness and refresh in the Python API?
check_freshness is a read-only operation that queries the backend state without modifying the source, returning a boolean indicating whether the indexed content matches the original. refresh is a write operation that triggers the backend to re-crawl the source URL or file and update the indexed text. While check_freshness returns True or False based on backend state, refresh returns True only to confirm that the refresh request was accepted and queued for processing.
How can I automate freshness checks in shell scripts using the CLI?
Use the notebooklm source stale command, which returns exit code 0 when the source is stale (action required) and exit code 1 when the source is fresh. This inverted logic allows straightforward conditional execution: if notebooklm source stale "$SRC_ID"; then notebooklm source refresh "$SRC_ID"; fi. The command also prints colored output—green for fresh, yellow for stale—providing visual feedback during interactive use while maintaining scriptable exit codes for automation.
What payload format does the SDK use when calling the NotebookLM RPC methods?
Both check_freshness and refresh use a three-element list payload: [None, [source_id], [2]]. The first element is always None, the second is a list containing the source UUID string, and the third is a list containing the integer 2. This format is required by the NotebookLM backend RPC interface and is hardcoded in src/notebooklm/_sources.py for both the RPCMethod.REFRESH_SOURCE (ID FLmJqe) and RPCMethod.CHECK_SOURCE_FRESHNESS (ID yR9Yof) method calls.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →