Key-Value Store
An Apify Key-Value Store is a flexible storage system for saving and reading data records identified by unique string keys. Unlike Datasets, which store rows of tabular data, Key-Value Stores handle any content type: screenshots (PNG, JPEG), HTML snapshots, PDF reports, JSON configuration files, binary downloads, XML feeds, plain text, or arbitrary binary data. Every actor run gets a default Key-Value Store automatically, and you can create additional named stores that persist across runs. Key-Value Stores matter because not all actor output is tabular. A screenshot monitoring actor produces images, not spreadsheet rows. A PDF generation actor produces documents. A configuration actor stores settings that other actors read. An AI actor might store model outputs, embeddings, or intermediate computation results. Without Key-Value Stores, you would need to base64-encode binary data into dataset JSON fields (wasteful and slow) or set up external storage like S3 (unnecessary complexity when Apify provides it natively). To use a Key-Value Store in your actor: await Actor.setValue('my-key', data) saves a record, and const data = await Actor.getValue('my-key') retrieves it. For binary data, specify the content type: await Actor.setValue('screenshot', buffer, { contentType: 'image/png' }). The special key 'INPUT' holds the actor's input parameters (read-only), and the key 'OUTPUT' is conventionally used for a summary result that appears in the actor run's Output tab in the Console. Access Key-Value Store records via the API at GET /v2/key-value-stores/{storeId}/records/{key}. This returns the raw content with the appropriate Content-Type header, so images are served as images, JSON as JSON, and so on. This makes Key-Value Stores excellent for serving public assets — you can share a direct URL to a screenshot or report without any authentication if the store is set to public. From the CLI: apify kv-store get-record --store-name my-store --key my-key. Using the client library: const store = await Actor.openKeyValueStore('my-store'); await store.setValue('report', pdfBuffer, { contentType: 'application/pdf' }); const report = await store.getValue('report'); Common mistakes include using Datasets for everything when Key-Value Stores are more appropriate. If your output is a single report, a configuration object, a set of images, or any non-tabular data, use a Key-Value Store. Another mistake is not using named stores for data that should persist across runs — the default store is tied to a single run and follows run retention rules, but a named store (opened with Actor.openKeyValueStore('persistent-config')) persists independently. Forgetting to set the correct contentType when saving binary data is also common: without it, the API serves the data as application/octet-stream, which breaks browser rendering of images and PDFs. Key-Value Stores are also the mechanism for sharing state between actors in a pipeline. Actor A can save intermediate results to a named store, and Actor B can read from the same store by name. This is more efficient than passing large payloads through Actor.call() input parameters, which have a 1 MB size limit. Storage retention follows your Apify plan: 7 days free, 14-30 days on paid plans. Named stores can be explicitly set to persist longer. Each record in a Key-Value Store can be up to 10 MB in size. For larger files, consider splitting them across multiple keys or using external storage. Monitor your storage usage in the Apify Console under the Storage tab. Related concepts: Dataset, Actor Run, Input Schema, Actor.