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

# How to Get FRED Data into Snowflake (3 Ways)

> Three ways to get FRED economic data into Snowflake: a Marketplace listing, Snowflake's Data Utilities app, or a FRED API pipeline, with SQL and Python for each.

*By [Fruit Stand Team](https://fruitstand.dev/about.md) · November 2, 2026 · Guides*

There are three ways to get FRED data into Snowflake: subscribe to a
**Snowflake Marketplace listing** that already has the series loaded, call
the FRED API from SQL with Snowflake's free **Data Utilities app**, or run
your own **FRED API pipeline** in Python. A Marketplace listing is the
fastest. Every series is queryable within minutes, with nothing to build or
schedule.

The Data Utilities app is a good fit for a handful of series. A pipeline
gives you full control, but the FRED API allows 120 requests a minute, so
a one-request-per-series backfill of 250,000 series takes more than a day.

## The short answer

| Method | Time to first query | Ongoing work | Best for |
| - | - | - | - |
| Snowflake Marketplace listing | Minutes | None, the provider refreshes it | Most teams; anyone who needs more than a few series |
| Snowflake Data Utilities app | Under an hour | Rerunning the download to pick up new data and revisions | A short, fixed list of series |
| FRED API pipeline (Python, dlt, Portable) | Days | Rate limits, revisions, new series, retries | Custom transforms or series no listing carries |

The rest of this post walks through each option, with code and the gotchas
that show up once the pipeline is running.

## Option 1: Subscribe to a Snowflake Marketplace listing

Marketplace data is delivered through Snowflake's secure data sharing. The
provider's tables appear as a read-only database in your account. Nothing
is copied, you don't pay storage for it, and each refresh appears without
you doing anything. You pay for the warehouse compute your queries use,
plus the listing's price.

**1. Find the listing**

Search the Snowflake Marketplace for FRED. The [FRED Series listing](https://app.snowflake.com/marketplace/listing/GZTYZ40XYNE) has 250,000+ FRED series with full history, refreshed daily, and a free 30-day trial.

**2. Get it**

Click **Get**, choose the database name the listing will be mounted as, and pick which roles can access it.

**3. Query it**

Select that database in a worksheet and query the tables by FRED series ID.

Once it's mounted, series are queried by the same IDs you see on the FRED
website. Year-over-year CPI inflation, for example:

```sql theme={null}
select
    date,
    value as cpi,
    value / lag(value, 12) over (order by date) - 1 as cpi_yoy
from fred.fred_series_observations_vw
where series_id = 'CPIAUCSL'
order by date desc
limit 12;
```

Each observation row carries the series' units, frequency and seasonal
adjustment, so you don't need a separate metadata lookup to label a chart.
The listing also includes every revision of each observation (ALFRED
vintages) in `fred_series_observations_vintages_vw`, covered
[below](#vintage-observations-keeping-every-revision). The schema is in the
[FRED Series docs](https://fruitstand.dev/datasets/fred-series.md).

**What about Snowflake Curated Data?** Snowflake's own Marketplace data
(formerly Cybersyn) includes economic indicators such as CPI, GDP, PCE,
jobless claims and interest rates. It loads them from the original
publishers, such as the BEA and the Federal Reserve, not from FRED. Series
use Snowflake's own variable IDs, such as `BEA_NIPA_PCE_2.8.4_DPCCRG_M_SA`,
rather than FRED IDs like `PCEPILFE`, and the free tier is delayed by three
months. It's a good option if its indicators cover what you need and you
don't need to match FRED series IDs. If your models, notebooks or
colleagues refer to FRED IDs, a FRED listing saves you a crosswalk.

## Option 2: Call the FRED API from SQL with Snowflake Data Utilities

Snowflake publishes a free native app, **Snowflake Data Utilities**, that
includes FRED functions. It calls the FRED API from inside Snowflake using
your own API key, which you can request free from the FRED website. Install
the app from the Marketplace, then give it network access and your key:

```sql theme={null}
create or replace network rule my_db.my_schema.fred_network_rule
    mode = egress
    type = host_port
    value_list = ('api.stlouisfed.org');

create or replace secret my_db.my_schema.fred_api_key
    type = generic_string
    secret_string = '<your FRED API key>';

create or replace external access integration fred_external_access_integration
    allowed_network_rules = (my_db.my_schema.fred_network_rule)
    allowed_authentication_secrets = (my_db.my_schema.fred_api_key)
    enabled = true;

grant usage on database my_db to application SnowflakeDataUtilitiesApp;
grant usage on schema my_db.my_schema to application SnowflakeDataUtilitiesApp;
grant usage on integration fred_external_access_integration to application SnowflakeDataUtilitiesApp;
grant read on secret my_db.my_schema.fred_api_key to application SnowflakeDataUtilitiesApp;

call SnowflakeDataUtilitiesApp.utils.init_fred(
    api_key => 'my_db.my_schema.fred_api_key',
    external_integration => 'FRED_EXTERNAL_ACCESS_INTEGRATION');
```

Creating the network rule, secret and integration needs a role with those
privileges, usually `ACCOUNTADMIN` or one your admin sets up. Then download
the series you want in one call:

```sql theme={null}
call SnowflakeDataUtilitiesApp.utils.fred_download_and_generate_foundation_tables_from_series(
    series_ids_string => 'GDP,CPIAUCSL,UNRATE',
    output_timeseries_table => 'FRED_TS',
    output_attributes_table => 'FRED_ATT'
);

select * from SnowflakeDataUtilitiesApp.utils.fred_ts limit 10;
```

This works well for a short list of series you already know the IDs of.
Keep these limits in mind:

* **You list every series.** The app downloads the IDs you pass. Finding
  series and adding new ones is up to you.
* **It's a snapshot.** The tables only change when you rerun the download.
  Schedule it with a Snowflake task to keep data current. Snowflake's docs
  recommend regular full refreshes, because FRED data is revised.
* **The rate limit still applies.** Calls go to the FRED API under your
  key, so the limit of 120 requests a minute applies here too.

## Option 3: Run your own FRED API pipeline

For full control, call the FRED API directly from Python and write the
results to Snowflake. The `fred/series/observations` endpoint returns up to
100,000 observations per request, which is the full history of almost any
series in one call:

```python theme={null}
import os

import pandas as pd
import requests
import snowflake.connector
from snowflake.connector.pandas_tools import write_pandas

FRED_URL = "https://api.stlouisfed.org/fred/series/observations"


def fetch_series(series_id):
    resp = requests.get(
        FRED_URL,
        params={"series_id": series_id, "api_key": os.environ["FRED_API_KEY"], "file_type": "json"},
        timeout=30,
    )
    resp.raise_for_status()
    df = pd.DataFrame(resp.json()["observations"])[["date", "value"]]
    df["series_id"] = series_id
    # FRED marks missing observations with "." instead of a number.
    df["value"] = pd.to_numeric(df["value"], errors="coerce")
    return df


df = pd.concat(fetch_series(s) for s in ["GDP", "CPIAUCSL", "UNRATE"])
df.columns = [c.upper() for c in df.columns]

conn = snowflake.connector.connect(
    account=os.environ["SNOWFLAKE_ACCOUNT"],
    user=os.environ["SNOWFLAKE_USER"],
    password=os.environ["SNOWFLAKE_PASSWORD"],
    warehouse="LOAD_WH",
    database="ECON",
    schema="RAW",
)
write_pandas(conn, df, "FRED_OBSERVATIONS_STAGING", auto_create_table=True, overwrite=True)
```

Then `MERGE` the staging table into your main table on `series_id` and
`date`, so revised values overwrite the old ones:

```sql theme={null}
merge into fred_observations t
using fred_observations_staging s
    on t.series_id = s.series_id and t.date = s.date
when matched then update set value = s.value
when not matched then insert (series_id, date, value)
    values (s.series_id, s.date, s.value);
```

If you'd rather not write the request code, dlt's REST API source can be
pointed at the FRED endpoints and load straight into Snowflake, and
Portable offers a managed FRED connector with Snowflake as a destination.
Both still call the same API under your key.

Plan for this work before committing to a pipeline:

* **The rate limit.** FRED allows up to 120 requests a minute and returns
  HTTP 429 beyond that. Repeated violations can get your key temporarily
  blocked. At one request per series, 250,000 series take at least 35
  hours, before retries. FRED's API version 2 can return every series on a
  release in bulk (`fred/v2/release/observations`), which cuts the request
  count for large backfills, but you have to work out which releases you
  need.
* **Revisions.** FRED values are revised after they're first published,
  GDP being the best-known example. An append-only load keeps the first
  print forever. Refetch full history for updated series and `MERGE` it,
  as above. To keep the earlier values too, see
  [vintage observations](#vintage-observations-keeping-every-revision) below.
* **Incremental updates.** The `fred/series/updates` endpoint lists the
  series updated recently. Use it to refetch only what changed instead of
  every series every day.
* **Missing values.** Missing observations come back as `"."`, not null.
  Convert them before loading, or numeric columns fail to load.
* **Metadata.** Units, frequency and seasonal adjustment come from a
  separate endpoint (`fred/series`). Without them, a column of numbers is
  hard to interpret.
* **Licensing.** Most FRED series are public domain, but some belong to
  third parties, and FRED's terms say you need the owner's permission to
  use those beyond personal use. Copyrighted series say so in their notes.

## Vintage observations: keeping every revision

The pipeline above keeps the latest value of each observation, which is
what FRED shows. Revised values overwrite the first print. That's fine for
most dashboards, but not for a backtest or a forecast evaluation. A model
trained on today's revised GDP uses numbers nobody had at the time, which is
look-ahead bias.

FRED's archive, **ALFRED**, keeps every version of every observation. You
get it from the same `fred/series/observations` endpoint by asking for the
full real-time period:

```text theme={null}
https://api.stlouisfed.org/fred/series/observations
    ?series_id=GDP
    &realtime_start=1776-07-04
    &realtime_end=9999-12-31
    &file_type=json
    &api_key=...
```

Each row then carries a `realtime_start` and `realtime_end`: the period
during which that value was the published one. The current value has a
`realtime_end` of `9999-12-31`. Store all four columns, and a point-in-time
query becomes a range filter. GDP as it was known on March 1, 2020:

```sql theme={null}
select date, value
from fred_observation_vintages
where series_id = 'GDP'
  and '2020-03-01' between realtime_start and realtime_end
order by date;
```

Loading vintages is much harder to maintain than loading latest values:

* **Requests are capped by vintage count.** FRED limits how many vintage
  dates one request can cover: 2,000 for JSON, 1,000 for CSV, and fewer for
  some daily series. Heavily revised series need several requests over
  consecutive real-time windows.
* **Windows have to be stitched.** Rows that span a window boundary come
  back clipped to the window. Merge adjacent rows with the same value, or
  one real-time period shows up as two.
* **Volume grows fast.** Weekly series that are revised often, such as some
  of the Federal Reserve's H.8 bank balance sheet series, have 700+ vintages
  and hundreds of thousands of rows each. When we built the vintage tables
  for our listing, full vintage history came to about 550 million rows and
  took 1.2 million API calls. At 120 requests a minute, that's about a week of
  calls for the initial load alone.
* **Updates rewrite history.** Every revision closes the `realtime_end` of
  the previous row and adds a new one. The reliable approach is to refetch
  each updated series' full vintage history and replace it, rather than
  trying to patch rows in place.
* **Not every series has vintages.** Some licensed series return an error
  saying they don't exist in ALFRED, so handle that per series instead of
  failing the whole run.

If you only need first prints, `output_type=4` returns each observation's
initial release, one row per date, with far less data.

**The FRED Series listing includes vintages.** Every revision is already
loaded in `fred_series_observations_vintages_vw`, with `realtime_start`,
`realtime_end` and an `is_current` flag on each row, so the point-in-time
query above works without building any of this. Vintage dates for each
series are in `fred_series_vintage_dates_vw`:

```sql theme={null}
select date, value
from fred.fred_series_observations_vintages_vw
where series_id = 'GDP'
  and '2020-03-01' between realtime_start and realtime_end
order by date;
```

## Check your load

Whichever method you pick, run two checks before trusting the data. First,
there should be exactly one row per series per date:

```sql theme={null}
select series_id, date, count(*) as rows_per_date
from fred_observations
group by series_id, date
having count(*) > 1;
```

Second, see when each series last got a new observation:

```sql theme={null}
select series_id, max(date) as latest_date
from fred_observations
group by series_id
order by latest_date;
```

The first query should return nothing. For the second, compare each
series' latest date to its frequency. A monthly series that's three months
behind may have a failed load, or FRED may have discontinued it.

## Which should you choose?

* **You want to analyze economic data, not maintain a pipeline:** use a
  Marketplace listing.
* **You need a few series and are fine refreshing them yourself:** use the
  Snowflake Data Utilities app.
* **You need custom transforms or a series no listing carries:** build the
  API pipeline, and budget for the rate limit and revisions.

## F.A.Q.

> [accordion] Is FRED data free to use in Snowflake?
>
> The FRED API is free with an API key, so Option 2 and Option 3 cost only your Snowflake compute and engineering time. Most series are public domain, but check the notes of any series marked as copyrighted. The [FRED Series listing](https://app.snowflake.com/marketplace/listing/GZTYZ40XYNE) has a free 30-day trial, then it's \$150/month flat, with 250,000+ series already loaded and refreshed daily.

> [accordion] Does Snowflake Curated Data include FRED?
>
> Not as FRED series. Snowflake Curated Data publishes economic indicators such as CPI, GDP and interest rates from the original sources, like the BEA and the Federal Reserve, under its own variable IDs. To query by FRED series ID, use a FRED listing or load the series from the FRED API.

> [accordion] How do I get FRED data as it was originally published?
>
> Request the observations with `realtime_start=1776-07-04` and `realtime_end=9999-12-31` to get every vintage from ALFRED, FRED's archive, or use `output_type=4` for first releases only. Store `realtime_start` and `realtime_end` with each value, and filter on them to see a series as of any past date. The [FRED Series listing](https://app.snowflake.com/marketplace/listing/GZTYZ40XYNE) already includes every vintage in `fred_series_observations_vintages_vw`.

> [accordion] What is the FRED API rate limit?
>
> Up to 120 requests per minute per API key. Requests beyond that get an HTTP 429 error, and repeated violations can lead to a temporary block.

> [accordion] How often is FRED data updated in the Marketplace listing?
>
> The FRED Series listing refreshes observations daily with an incremental load, so revised and newly released values appear the next morning. Releases are refreshed monthly, and categories and tags quarterly.

> [accordion] Can I join FRED data with stock prices in Snowflake?
>
> Yes. A mounted listing is queried like any other database, so you can join FRED series to your own tables or to other listings, such as [Historical Stock Prices](https://fruitstand.dev/datasets/historical-stock-prices.md), on date. See [How to Get Historical Stock Prices into Snowflake](https://fruitstand.dev/blog/historical-stock-prices-into-snowflake.md) for loading prices.

To skip building the pipeline, start a free 30-day trial of the
[FRED Series listing on the Snowflake Marketplace](https://app.snowflake.com/marketplace/listing/GZTYZ40XYNE).
It has 250,000+ FRED series with full history and every vintage, refreshed daily, for
\$150/month flat after the trial. The schema and more queries are in the
[dataset docs](https://fruitstand.dev/datasets/fred-series.md). Questions? Reach out at
[contact@fruitstand.dev](mailto:contact@fruitstand.dev).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.