> ## Documentation Index
> Fetch the complete documentation index at: https://intunedhq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Persist data with KV cache

## Recipe

This recipe shows how to use [`persistentStore`](/main/05-references/runtime-sdk-typescript/persistent-store) (TypeScript) or [`persistent_store`](/main/05-references/runtime-sdk-python/persistent-store) (Python) to cache scraped data across executions of the same project.

<CodeGroup dropdown>
  ```typescript TypeScript theme={null}
  import { BrowserContext, Page } from "playwright";
  import { persistentStore } from "@intuned/runtime";

  interface Params {}

  export default async function handler(
    params: Params,
    page: Page,
    context: BrowserContext
  ) {
    const CACHE_KEY = "consultations";

    // 1. Check cache first
    const cached = await persistentStore.get(CACHE_KEY);
    if (cached) {
      return cached;
    }

    // 2. Cache miss — navigate and scrape the page
    await page.goto("https://sandbox.intuned.dev/consultations/list");
    await page.waitForSelector(".consultation-item");

    const consultations = await page.locator(".consultation-item").evaluateAll(
      (items) =>
        items.map((item) => ({
          id: item.getAttribute("data-consultation-id"),
          status: item.querySelector(".consultation-status")?.textContent?.trim(),
          name: item.querySelector(".client-name .data-value")?.textContent?.trim(),
          date: item.querySelector(".consultation-date .data-value")?.textContent?.trim(),
          topic: item.querySelector(".consultation-topic .data-value")?.textContent?.trim(),
        }))
    );

    // 3. Store for future runs
    await persistentStore.set(CACHE_KEY, consultations);

    return consultations;
  }
  ```

  ```python Python theme={null}
  from playwright.async_api import Page
  from intuned_runtime import persistent_store
  from typing import Any, Dict


  async def automation(page: Page, params: Dict[str, Any] | None = None, **_kwargs):
      CACHE_KEY = "consultations"

      # 1. Check cache first
      cached = await persistent_store.get(CACHE_KEY)
      if cached:
          return cached

      # 2. Cache miss — navigate and scrape the page
      await page.goto("https://sandbox.intuned.dev/consultations/list")
      await page.wait_for_selector(".consultation-item")

      items = await page.locator(".consultation-item").all()
      consultations = []
      for item in items:
          consultations.append({
              "id": await item.get_attribute("data-consultation-id"),
              "status": await item.locator(".consultation-status").inner_text(),
              "name": await item.locator(".client-name .data-value").inner_text(),
              "date": await item.locator(".consultation-date .data-value").inner_text(),
              "topic": await item.locator(".consultation-topic .data-value").inner_text(),
          })

      # 3. Store for future runs
      await persistent_store.set(CACHE_KEY, consultations)

      return consultations
  ```
</CodeGroup>

## How it works

1. **Check the cache** — Use `persistentStore.get()` / `persistent_store.get()` to look for existing data.
2. **Return cached data** — If found, return immediately without re-scraping.
3. **Scrape and store** — On cache miss, navigate to the page, extract data, and store it with `persistentStore.set()` / `persistent_store.set()` for future runs.

Data persists across all executions within the same project, making it ideal for data that doesn't change frequently.

## Related SDK methods

<CardGroup cols={2}>
  <Card title="persistentStore (TypeScript)" icon="js" href="/main/05-references/runtime-sdk-typescript/persistent-store">
    TypeScript SDK helper for persistent key-value storage
  </Card>

  <Card title="persistent_store (Python)" icon="python" href="/main/05-references/runtime-sdk-python/persistent-store">
    Python SDK helper for persistent key-value storage
  </Card>
</CardGroup>
