Skip to content
datastore.sh

How to Download Solana Transaction History at Scale: RPC, APIs, Archives and Parquet

Learn how to download Solana transaction history at scale. Compare RPC, indexed APIs, raw archives and Parquet datasets, then build a reliable pipeline for backfills, analytics and backtesting.

Data Platform13 min read

If you need to download Solana transaction history, the right solution depends on what “history” means for your workload.

Do you need transactions involving one wallet? Every transaction for a program over six months? Raw instructions and logs? Every Pump.fun buy? A reproducible dataset that you can query hundreds of times for backtests or machine-learning features?

Those requirements sound similar, but they have very different architectures.

The common failure mode is using an RPC endpoint designed for point lookups as if it were a bulk historical warehouse. It may work for a proof of concept. It becomes slow, expensive and difficult to validate once the job includes millions of transactions or repeated analysis.

This guide compares the practical ways to get Solana history—RPC, indexed APIs, raw archives and prepared Parquet datasets—and explains how to choose and validate the right one.

Quick answer: which method should you use?

RequirementUsually the best starting point
Look up one known transactionRPC getTransaction
List transactions referencing one addressRPC getSignaturesForAddress or an indexed API
Retrieve a small recent time rangeRPC/API
Build an application that queries history interactivelyIndexed API
Collect future events continuouslyGeyser/stream + your own storage
Build a universal historical Solana indexerArchive data + custom decoder/indexer
Study one protocol across months or yearsDecoded protocol dataset
Run repeated analytics/backtests/ML featuresBulk Parquet in your own compute environment
Audit or reproduce a historical research resultVersioned files, manifest and checksums

The key principle is simple:

Use RPC for retrieval, an archive/indexer for raw reconstruction, and bulk files for repeated analytical scans.

What does “Solana transaction history” actually contain?

A Solana transaction is not naturally a row in a simple trade table.

A transaction can contain multiple top-level instructions, nested inner instructions, program logs, token-balance changes, address lookup tables and an execution result. One transaction may create an account, invoke an aggregator, swap through several pools and transfer fees—all in one atomic execution.

The official getTransaction RPC method returns a confirmed transaction by signature, or null when it is not found at the requested commitment. Its response can include the slot, block time, message/instructions, metadata, logs, balances and inner instructions. That is excellent for inspecting a known signature. It is not yet a semantic answer to “which Pump.fun buys happened?” or “what was DEX volume?”

For analytical use, distinguish these layers:

LayerTypical contentsBest for
TransactionSignature, account keys, top-level instructionsAudit and raw reconstruction
Execution metadataLogs, inner instructions, balances, error statusProgram decoding and token-flow analysis
Decoded instruction/eventNamed protocol action and typed fieldsProtocol analytics
Derived market/state tablePrice, liquidity, balances, labelsSpecific research questions

Option 1: Use Solana RPC

Solana JSON-RPC is the right first tool for many small history jobs.

Find signatures for an address

The official getSignaturesForAddress method returns confirmed transaction signatures for transactions whose account keys reference a specified address. Results are ordered newest to oldest and include signature, slot, error, block time and confirmation status. It supports pagination controls such as before and until.

Conceptually:

text
address → page of signatures → fetch each signature → decode/store

This works well when you need:

  • a small wallet’s transaction list;
  • activity for one mint, account or program address;
  • an investigation around a known set of signatures;
  • a narrow reconciliation task.

Fetch a transaction by signature

Once you have a signature, call getTransaction. The official documentation shows that the response can include the transaction version, slot, block time, execution metadata and inner instructions.

At this stage, the work shifts from retrieval to interpretation. A token transfer in raw transaction metadata is not necessarily a DEX trade. A Jupiter transaction can have multiple liquidity legs. A failed transaction may still contain useful evidence for a reliability study but should not be counted as an executed trade.

When RPC becomes the wrong architecture

RPC becomes awkward when you need to:

  • crawl many addresses or every transaction involving a program;
  • backfill long time ranges;
  • retrieve millions of signatures and full transaction bodies;
  • run the same historical scan repeatedly;
  • decode many protocol versions and inner instructions;
  • guarantee a reproducible research input;
  • handle provider limits, availability differences and gaps.

The problem is not that RPC is bad. It is simply designed as a request/response interface, not as your long-term columnar warehouse.

Option 2: Use an indexed Solana API

Indexed APIs sit between raw RPC and a dataset you own.

They may provide higher-level queries such as transaction history by address, parsed actions, token transfers or program-specific events. They are useful for application backends and exploratory workflows because they avoid much of the raw decoding work.

Choose an indexed API when you need:

  • searchable history for users or wallets;
  • application queries with low integration overhead;
  • current plus recent historical results;
  • a small number of narrowly-scoped data products.

Ask four questions before relying on one for a historical project:

  1. What is the exact retention/coverage for this endpoint?
  2. Is the data raw, parsed or derived?
  3. Are failed transactions and inner instructions included?
  4. Can you export and retain the full result, with a stable version?

An API can be excellent for serving an app while still being the wrong foundation for a 200-run historical research program.

Option 3: Build from raw archive data

If you need arbitrary Solana history and want complete control over the output, build your own archival indexing pipeline.

The pipeline usually looks like this:

text
historical blocks / transactions
→ transaction parser
→ program and inner-instruction decoder
→ normalized tables
→ validation and deduplication
→ warehouse / Parquet lake

This route is appropriate when you need to support unknown programs, preserve raw chain semantics, or develop your own canonical decoding rules.

It also carries the most engineering work.

What an archive/indexer has to handle

At minimum, plan for:

  • legacy and versioned transactions;
  • address lookup tables;
  • outer and inner instruction paths;
  • program upgrades and changing instruction layouts;
  • logs and emitted events;
  • failed versus successful execution;
  • token decimals and Token-2022 extensions;
  • slot, block-time and transaction ordering;
  • skipped slots, missing metadata and retried ingestion;
  • storage, compaction, reprocessing and schema evolution.

The raw chain gives you evidence. It does not give you a ready-made swap, liquidity_add or token_creation table. Those are decoders and policies you must build, test and maintain.

Option 4: Download a prepared Solana dataset

If the goal is to analyse known protocols—not to build a universal indexer—a decoded bulk dataset can remove most of the reconstruction work.

This is the model used by datastore.sh’s Solana data catalog. It provides documented protocol-level Solana data as typed, versioned Parquet files rather than a proprietary historical query API. The catalog describes decoded instructions, events and state tables, with coverage specific to each dataset and selected window.

For example, if your question is:

“Which Pump.fun tokens reached 100 unique buyers in their first minute, and how did they trade after migrating to PumpSwap?”

you want decoded creation, trade, completion/migration and PumpSwap records—not an undifferentiated collection of transaction JSON.

Prepared data is especially useful when you need to:

  • query the same historical universe repeatedly;
  • use DuckDB, Polars, ClickHouse, Spark or a warehouse;
  • join several protocol tables;
  • hand the dataset to analysts or model-training jobs;
  • associate every research result with an immutable input version.

Raw transactions vs decoded protocol data

Neither is universally better.

If you need…Prefer…Why
Unrecognized programs or custom interpretationRaw transactionsYou control the decoder
A chain-level audit trailRaw transactions + metadataKeeps full execution evidence
Pump.fun trade analysisDecoded Pump.fun recordsAvoids repeated instruction/event parsing
DEX volume by venueDecoded DEX swaps plus route rulesRaw token transfers are ambiguous
Wallet history UIIndexed APIFast targeted retrieval
Repeated protocol researchPartitioned ParquetEfficient scans and reproducible inputs
Live collection going forwardStream + raw storage/decoderCaptures events as they occur

The best systems often retain both layers: raw provenance for auditability and decoded tables for analysis.

Why Parquet is useful for large Solana history

Transaction JSON is a natural transport format. It is often a poor format for repeated analytics.

Parquet is columnar. When a query needs only six fields from a 40-column decoded event table, an analytical engine can read the relevant columns instead of reparsing complete JSON documents and nested arrays each time.

For example, this query needs no full transaction logs:

sql
SELECT
  mint,
  COUNT(DISTINCT user) AS unique_buyers,
  SUM(sol_amount) AS sol_volume
FROM read_parquet('pumpfun/trade_event/date=*/part-*.parquet')
WHERE is_buy = TRUE
GROUP BY mint
ORDER BY sol_volume DESC;

Parquet also works with common analytical tooling:

  • DuckDB;
  • Polars;
  • ClickHouse;
  • Spark;
  • Snowflake;
  • BigQuery.

This makes the historical input portable. Your research should not have to depend on making the same paid API request every time a feature changes.

A reliable Solana history download architecture

For a large, repeatable historical job, structure the workflow as an ingestion project, not a script that keeps retrying API calls.

1. Write the coverage contract first

Define:

  • network: mainnet-beta, devnet or another cluster;
  • start/end slots and timestamps;
  • target universe: accounts, programs, mints or all transactions;
  • finalized versus confirmed commitment policy;
  • successful-only or successful-and-failed inclusion;
  • raw, decoded or derived output;
  • expected order of magnitude and storage budget.

“All Solana transactions from January” is incomplete. “All successful instructions emitted by program X between finalized slot A and finalized slot B, with inner instructions and logs” is a usable contract.

2. Choose the source and retain its identity

Record:

  • provider/source name;
  • endpoint or dataset version;
  • request parameters or coverage manifest;
  • start and end cursor/slot;
  • retrieval timestamp;
  • any source-reported gaps or errors.

This is what lets you explain a result months later.

3. Land immutable raw or delivered files

Avoid silently overwriting history. Store the original response/file set, then create derived tables separately.

For bulk data, keep a delivery manifest that lists file paths, row counts where available, schema version and checksums. datastore.sh provides manifests and SHA-256 checksums for delivered Parquet files, which makes integrity checking part of the normal ingestion workflow rather than an afterthought.

4. Normalize and decode with explicit versioning

Use tables such as:

text
transactions
instructions
inner_instructions
logs
token_balance_changes
decoded_protocol_events

Every derived row should retain a path back to its signature and instruction position. A decoded Pump.fun trade without a traceable signature/instruction lineage is difficult to audit when the decoder changes.

5. Validate coverage before analysis

Check:

  • first and last slot/time actually present;
  • slot continuity within the requested range;
  • row counts by day/program;
  • failed/successful transaction proportions;
  • duplicate transaction/event records;
  • null rates in critical fields;
  • sample signatures against an independent source;
  • schema consistency across partitions.

Do this before running a long backtest. Fixing an unnoticed week-long gap after training a model wastes far more time than validating at ingest.

How to download history for common Solana workloads

One wallet

Start with getSignaturesForAddress or an indexed address-history API. Page through results, fetch transaction details as needed, and keep the cursor and stop condition. If you need only recent activity, this can be straightforward.

One program

For a small program or narrow date range, an indexed program API or targeted archive scan can work. For large protocol history, use a decoded protocol dataset or build a program-specific indexer. Scanning all raw transactions and filtering afterward is usually wasteful.

One mint across several DEXs

Use decoded pool-level swaps and aggregation/routing records, then define the metric: user-facing swaps, pool legs, token transfers or price observations. Do not assume every token transfer is a trade.

Full market backtesting

Land immutable bulk files locally or in a warehouse. Build event-time feature tables, preserve every input version, and simulate execution with fees, liquidity and strict causality. An API-only loop will be slow and makes experiment reproducibility harder.

Common Solana transaction-history mistakes

Mistake 1: Treating an address signature list as complete business history

getSignaturesForAddress lists transactions that reference the address in accountKeys. You still need to fetch, decode and classify them. The address may be touched for many reasons unrelated to the business event you are studying.

Mistake 2: Treating every token transfer as a swap

Transfers can represent account setup, LP operations, fee movements, airdrops, program settlement or a multi-leg route. Use protocol semantics and transaction lineage.

Mistake 3: Ignoring inner instructions

Important work can occur through cross-program invocations. Solana’s getTransaction response includes inner instruction data; omitting it can make a decoder incomplete.

Mistake 4: Ignoring failed transactions without deciding to

For executed trade-volume research, failures are normally excluded. For latency, bot behaviour or reliability research, failures may be valuable. Make it an explicit policy.

Mistake 5: Using block time as the only ordering key

Multiple actions can share a time or a slot. Retain the transaction and instruction ordering information needed by your use case.

Mistake 6: Re-running the same archive extraction for every experiment

Separate one-time acquisition/normalization from repeatable analysis. Keep partitioned, validated data that feature jobs can scan directly.

Mistake 7: No manifest, no checksums, no reproducibility

If you cannot identify the precise files and schema that fed a historical result, it will be difficult to debug or trust later.

Questions to ask a Solana historical-data provider

Before choosing a source, ask:

  1. What exact date and slot range is available?
  2. Is the source raw transaction data, decoded events or derived tables?
  3. Are inner instructions, logs and token-balance metadata included?
  4. Are failed transactions included, excluded or labelled?
  5. How are program upgrades and transaction versions handled?
  6. What is the partitioning and file format?
  7. Can I inspect schemas and sample rows first?
  8. How are duplicate/replay records handled?
  9. Are coverage gaps documented?
  10. Are files versioned and checksummed?
  11. Can I retain the files and query them in my own infrastructure?
  12. Can every decoded row be traced back to a chain signature and instruction?

The answers matter more than an advertised transaction count.

Frequently asked questions

Can I download all Solana transactions?

Yes, but “all” requires an archive-scale source and a plan for large raw data volumes, storage, indexing and decoding. For a known protocol, a decoded protocol dataset is usually much more practical than starting from every chain transaction.

How do I get Solana transaction history for an address?

Use getSignaturesForAddress or an indexed history API to obtain a paginated list of signatures, then retrieve and parse the relevant transactions. Keep the pagination cursor, coverage policy and transaction-status rule.

Is an RPC node enough for historical Solana data?

It is enough for many small or targeted retrieval tasks. It becomes a poor default for full backfills, program-wide history and repeated analytical scans because you still have to retrieve, store, decode, validate and repeatedly query large raw responses.

What is the difference between Solana archive data and a historical dataset?

Archive data is closer to raw chain history. A historical dataset may already be organized into typed, protocol-specific tables. Archive data gives you maximum flexibility; a prepared dataset reduces the indexing and decoding work for known questions.

Can I use Solana historical data for backtesting?

Yes. Keep the exact data snapshot, enforce strict event-time causality, include relevant execution costs and avoid using features that were visible only after the simulated decision.

Does datastore.sh provide Solana transaction history?

datastore.sh provides downloadable historical Solana datasets as typed, versioned Parquet files. Its focus is decoded protocol instructions, events and state tables for research and analytics, rather than serving a metered historical query API.

The key takeaway

Downloading Solana transaction history is not one task. It is a choice between four data architectures.

Use RPC for known signatures and narrow address history. Use indexed APIs for application queries. Use raw archives when you need to build and control the decoder. Use documented Parquet datasets when your objective is repeated analysis of known protocols.

Choose the architecture based on the historical question you need to answer—not simply on who can return a transaction fastest.

Explore historical Solana data on datastore.sh to inspect protocol-specific schemas, samples and coverage windows before you start a large backfill.