John Carioto · October 3, 2026

The "ghost station" argument

Some U.S. weather stations stopped reporting years ago, yet NOAA still publishes monthly temperatures for them. I knew for a fact that this is true to an extent, but I am always sure that listening to one point of view means that (in today's world) I'm missing something. Since this resurfaces online every few months, and both sides of the argument argue the 'facts' of their side and disregard the other, I took some time this weekend to understand HOW we get this weather data.

One side calls these "ghost stations" and says NOAA fabricates their numbers. The other answers that NOAA doesn't use those stations at all, pointing to an "E" flag on every month since they closed.

The flag means something narrower than either side claimed. In the USHCN v2.5 readme, the data-measurement flag "E" has two meanings, and NOAA says the letter does not tell them apart: the month was estimated from neighboring stations because a monthly value could not be computed from the daily data, or the pairwise homogenization algorithm deleted the value because too many inhomogeneities sat close together. So the numbers exist, they are labeled, and they are not a silent fake. They are also not only closed stations. They sit in a legacy dataset that stopped being NOAA's official CONUS record in 2014. NOAA still produces the file. That doesn't mean the numbers aren't used though, which is where the argument rises.

Understanding what you get requires knowing where a temperature reading starts, what happens to it on the way to a national average, and how anyone checks the result. That is the rabbit hole I went down and what this article walks through.

Who takes the measurements

No single network measures the weather. The U.S. record is stitched together from volunteers (this part is...suspect to me personally, but ok), airports, purpose-built reference stations, ocean robots and balloons, each with different strengths and flaws.

Network Who runs it Size Since What it's good for
Cooperative Observer Program (COOP) NWS, with volunteers 8,700+ observers 1890 Long daily records of high, low and precipitation; the backbone of U.S. climate history
ASOS NWS, FAA, DoD about 950 active sites, mostly airports early 1990s Minute-by-minute automated readings for aviation and forecasting
U.S. Climate Reference Network (USCRN) NOAA 114 contiguous U.S., 25 Alaska, 2 Hawaii 2000s (useful CONUS density about 2004–2008) Pristine, stable sites built specifically to check long-term trends
Radiosondes NWS + other countries 92 NWS sites; over 800 worldwide 1930s Temperature, humidity and wind up to 35 km, twice a day
Argo floats International roughly 4,000 floats (the FAQ also says ~3,800) 1999 Core float: ocean temperature to 2,000 m, ±0.002 °C. Deep Argo is the one that goes to 6,000 m

Surprisingly, the COOP network matters most for this story. Its volunteers read thermometers once a day on farms, in towns and at parks, and NWS calls it the most definitive source on U.S. temperature trends because of its long, rural, stable records. It is also the network most prone to quiet changes: an observer retires, a thermometer moves, the reading time shifts. And this is why I think it's suspect. It's subject to the vagaries of human action. How many people didn't feel like going out and reading the sensor and just said "Eh, feels like 53 or so."

On top of these, though, sit satellites, aircraft reports, ship and buoy readings, and private networks such as state mesonets (lots of automated stations placed closely together). Forecasters use all of it. Climate datasets are pickier, because a trend is only as good as its longest consistent records. And the less said about that here, the better, but it's certainly related.

From a thermometer reading to a national record

A reading passes through several layers before it becomes a headline number, and each layer is a separate, public dataset you can download.

  1. GHCN-Daily is the raw archive. It holds daily records from more than 100,000 stations in 180 countries, about 25,000 of which report temperature, and it is the official archive for COOP data. Daily values are quality-checked and flagged, not homogenized.
  2. GHCN-Monthly v4 turns daily data into monthly averages for about 26,000 stations worldwide and corrects them for station changes. NOAA's global temperature record is built on it.
  3. nClimDiv is NOAA's official U.S. record. Since March 2014 it has drawn on 10,000+ stations from GHCN-Daily and spread them onto a fine grid that accounts for terrain. It is adjusted too: it applies the same time-of-observation and station-change corrections as USHCN (see Adjustments below). It does not write an estimated month back onto a closed station. It does fill every 5 km cell by climatologically aided interpolation (Vose et al. 2014). "Does not infill" is only true of the station record.
  4. USHCN v2.5 is the older U.S. record: a fixed list of 1,218 long-running stations. It is still produced. It is no longer the official CONUS record. Closed stations' estimated values live here, and so do other months flagged E. It is still used as a check on official data though.

The same raw archive feeds both the official record and the legacy one. Only USHCN writes an estimated month back onto a closed station. These are the ghost stations.

That last point is where the ghost-station argument goes wrong on both sides. USHCN keeps a fixed station list so its average stays comparable over time, so when a station closes, its months can be estimated from neighbors and flagged E. That is one reason for an E, not the only one. nClimDiv has no fixed list: a closed station stops contributing a station record, and the map is filled in at the grid instead.

For the HVAC work this site is built around: USHCN monthly final files and nClimDiv are climate-monitoring products, not ASHRAE design temperatures, TMY/TMYx, or hourly bin data (an E flag and a PHA shift do not appear in those files), GHCNd daily values are flagged rather than homogenized, nClimDiv HDD/CDD are gridded monthly monitoring degree-days rather than a coil or boiler load, and USCRN is not a TMY source.

TMY3, which is the file I actually use

The products above are how a national number gets made. They are not what I load when I am designing. TMY3 is. This part is near to my heart.

TMY3 is an NREL product, not NOAA climate monitoring. The users manual is Wilcox and Marion, NREL/TP-581-43156 (May 2008). It is derived from the 1991–2005 National Solar Radiation Database. That NSRDB update covers 1,454 U.S. locations. The TMY3 sets themselves are 1,020 locations, in the U.S. and its territories. The archive I point people at now is the NSRDB archives.

A TMY is one synthetic year of hourly solar and meteorological values. You build it by taking the multi-year record and, for each calendar month, picking a real month that was typical. It is for comparing solar systems and building energy systems. The manual says the file represents typical conditions, not extremes, so it is not for sizing to the worst case at a site.

TMY, TMY2, and TMY3 are not interchangeable. The time basis, the format, the elements, and the units differ. Treat them as different files.

So nobody takes the wrong file home: USHCN final files, nClimDiv, and USCRN are not a TMY or a TMYx, and they are not ASHRAE design temperatures. TMY3 is the hourly file an energy model loads. Peak coil and boiler sizing still comes from ASHRAE climatic design conditions, not from a typical year. "Used for design" is not the same sentence as "this is the 1% design day."

Quality control: catching bad readings

Automated checks flag about 0.3% of the nearly 2 billion values in GHCN-Daily, and NOAA estimates 98–99% of those flags catch real errors. Flagged values are marked and set aside, not deleted.

The checks look for things a human would find suspicious:

  • Impossible values: readings beyond world records, or a high below the same day's low.
  • Stuck instruments: 20 or more identical days in a row.
  • Spikes: a daily high more than 25 °C above that same station's day before and day after, not a comparison with the neighbors.
  • Copy errors: a whole year duplicated from another year or another station.
  • Disagreement with neighbors: a spatial check is a reading more than 8 °C off what nearby stations predict and a standardized residual over 4 standard deviations. The anomaly check is a reading more than 10 °C off those neighbors on the preceding day, the day itself, and the following day.

The full list is published, with the threshold for every test. Monthly datasets add their own checks and flags on top, which is where USHCN's lowercase letters (days missing) and the "E" data-measurement flag come from.

Adjustments: why NOAA changes the raw numbers

Raw data is correct for what the thermometer saw, but a station's history is full of changes that have nothing to do with climate. Adjustments try to remove those changes so that a 1950 reading and a 2020 reading mean the same thing.

Time of observation. A COOP volunteer reads a min/max thermometer once a day and resets it. Reset it at 5 p.m. on a hot afternoon, and the next "day" can record that same heat again; reset at 7 a.m., and a cold morning can count twice. Most stations moved from afternoon to morning readings to help precipitation measurements. Menne, Williams, and Palecki put that artificial cooling especially since 1950, not as a clean break in 1960 (Menne et al. 2010). Afternoon-to-morning is a real cooling bias, and the adjustment adds it back. The roughly 0.25 °C U.S. average for that bias is Hausfather's 2016 summary of it (Hausfather et al. 2016), not a NOAA product and not the 2003 paper. Menne, Williams, and Vose (2009) found the time-of-observation adjustment raises the 1895–2007 CONUS trend by about 0.015 °C per decade for the maximum and 0.022 °C per decade for the minimum. Vose et al. 2003 tested the Karl et al. 1986 method and found the residual generally under 0.05 °C. That is a check on the method. It is not the source of the 0.25 °C figure.

Instrument changes. Starting in the mid-1980s, most COOP stations swapped liquid-in-glass thermometers for electronic sensors (MMTS). Menne et al. 2010, paragraph 14, is the average of all the unadjusted transitions, not the older Quayle network constants: about −0.1 °C on the daily max and about +0.025 °C on the daily min, a net cooling bias (Menne et al. 2010). He also says the version 2 maximum adjustment is still a bit small.

Station moves and local changes. A thermometer moves across town, a parking lot gets paved next to it, a tree grows. NOAA's Pairwise Homogenization Algorithm compares each station with many neighbors. A sudden jump at one station that its neighbors don't share is treated as an artifact and corrected. The correction is the size of the jump: the algorithm measures how much the gap between that station and its steady neighbors changed at the break, then shifts the station's earlier readings by that amount so the record lines up across the break.

Infilling. When a monthly value cannot be computed from the daily data, USHCN's final file fills it from nearby stations and marks it "E." A closed station is the screenshot everyone passes around. The same letter is also what you get when the pairwise algorithm deletes a value because too many inhomogeneities sat close together, and the file does not say which one you are looking at. Berkeley Earth tested U.S. temperatures with and without the infilled values and found it makes little difference to the result. Its author still called infilling a poor choice because it confuses people more than it helps.

The net effect matters for the argument: in the U.S., the biggest corrections remove cooling biases, so adjusted data shows more warming than raw data. Every raw, adjusted and estimated value is published side by side, so the size of each correction can be checked.

How anyone knows it's right

The strongest check is that independent measurements, built by different people with different methods, land in the same place. Four of them that appear to matter most are described below.

A network built so it should not need adjustments. That is the design intent. USCRN stations sit in stable rural spots chosen so the site won't change. The program still flags EXCEPTION values and keeps them out of the calculations, so "used as-is" is the goal, not a promise that every reading sails through. Each station carries three independent platinum thermometers in fan-ventilated sun shields, so a failing sensor shows up as disagreement with the other two, and instruments are calibrated or checked every year. Station readings are not estimated; only the national average involves interpolation, to spread about 114 points over the lower 48 states. A 2016 peer-reviewed comparison of nearby station pairs, January 2004 through August 2015, found the adjustments made USHCN stations look more like their USCRN neighbors, not less. In that short overlap, raw and adjusted USHCN are largely the same at the CONUS mean for minimum and mean temperature, and both the raw and the adjusted maximum trends stay below USCRN. That paper is a neighbor check. It does not say the adjustments raised the national trend up to the USCRN trend. A ~20-year CONUS rate is a noisy thing to hang a verdict on, and those particular rates were never a NOAA product.

Independent rebuilds by skeptics. Physicist Richard Muller doubted the temperature record and founded Berkeley Earth in 2010 to redo it from scratch, with partial funding from the Charles Koch Foundation. His team merged 14.4 million land observations from 44,455 sites and confirmed the warming. NASA, the UK Met Office, Japan's weather agency and Europe's Copernicus service each run their own versions too.

A record with no adjustments at all. All raw readings are public, so anyone can build an unadjusted global record. Carbon Brief did (Zeke Hausfather, 19 July 2017). The 36% less warming since 1880 is the ocean record only, mostly from correcting old bucket-over-the-side measurements. Combined global adjusted data, 1880–2016, warms more than 20% slower than the raw series. Since 1970 it flips: adjustments make the global trend about 4% faster, not 4% smaller, and the land-only figure in that piece is about 3% faster. One caveat: in 2009 the UK's Climatic Research Unit acknowledged that, for lack of storage in the 1980s, it had kept only adjusted versions of some station series. The originals were still held by the national weather services that collected them, CRU released its raw data by 2011, and independent reviews found no fraud, though they faulted the unit's lack of openness.

Measurements that don't use thermometers on the ground. Satellites infer atmospheric temperature from microwave emissions. The UAH satellite record, run by two prominent skeptics, is a lower-troposphere temperature, not a surface temperature. About 0.13 °C per decade is a fair ordinary-least-squares figure for the global lower troposphere from January 1979 through December 2019 (about 0.132). The current full-record header on the dataset is 0.16 °C per decade. The 0.13 printed in the file header is the ocean trend, not the global one. It runs lower than the rival RSS record, and it is still warming. Argo floats, weather balloons, shrinking sea ice and rising sea levels are further independent lines.

Where the critics have a point

The evidence for warming is strong, but several criticisms of how the U.S. record is built are fair and some remain open.

Criticism What's true Where it stands
Ghost stations USHCN still publishes a value, flagged E, for stations that closed years ago. Not a silent fake, and not only closed stations. The readme gives E two meanings and says the flag does not tell them apart. nClimDiv does not write that month back onto the closed station. Easy to misread. Even Berkeley Earth's analyst called infilling a confusing choice.
Poor station siting A volunteer survey covered 82.5% of USHCN stations and photographed many next to pavement, buildings and AC units. The peer-reviewed study of that survey found poorer siting overestimates minimum-temperature trends and underestimates maximum-temperature trends, leaving mean trends nearly unchanged. Later critic analyses claim more, but have not been through the same review.
Urban warming spreading Comparing stations to neighbors could, in principle, pass a city's warming onto rural sites ("urban blending"). NOAA says its adjustments largely remove siting and instrument effects. The 2016 station-pair paper is the comparison I would use. It does not show the adjustments lifting the CONUS trend up to USCRN.
A moving target USHCN is reprocessed in place. Readme §4.2 says old processed versions are not kept in an online archive, and each new file overwrites the last. A real reproducibility problem for USHCN. It is not a claim about GHCN-Daily.
Short reference period Useful USCRN density over the lower 48 is about 2004–2008, not a hard start in 2005. Calling the network ~2% of the planet is a shrug, not a coverage statistic. It can speak to recent U.S. trends, not a 1930s-versus-today comparison. Those still depend on adjusted COOP data.

The fixes are mostly about transparency: retire USHCN or drop closed stations from it, archive every processed version, and publish station-by-station adjustment logs in plain language.

How to check a claim yourself

Almost every viral temperature claim can be tested with free public files and a few lines of code.

  1. Find out which dataset the screenshot came from. A file name ending in FLs.52j is the live USHCN final adjusted temperature file. The readme's examples still say FLs.52i. raw is unadjusted. .dly is GHCN-Daily. The temperature parser below is not for the precipitation files.
  2. Read the flags before the numbers. In USHCN, "E" on the data-measurement flag is the two-meaning flag above (neighbors, or removed by homogenization), and it does not say which. Lowercase a–i mean that many days were missing, and -9999 means no value. Each dataset's readme defines its flags.
  3. Compare raw and adjusted for the same station. If a claim is about adjustments, the size and direction of the change is right there.
  4. Check against USCRN. Once the lower-48 network is dense enough to use, about 2004–2008 rather than a hard line at 2005, a nearby reference station is the cleanest test.
  5. Ask whether the dataset is the one that matters. A problem in USHCN doesn't touch nClimDiv, and a problem in one U.S. station doesn't touch the global record.

Applied to a ghost station, that process gives a clear answer: the estimates are real, labeled, confined to a legacy dataset, and too small to move any trend that matters. Both sides of the usual argument would be more accurate after step 2.

Try it: count NOAA's estimated values

This Python script (standard library only, Python 3.8+) downloads NOAA's USHCN final average-temperature tarball, about 5.9 MB, one file per station. It reports what share of each year's monthly values carry "E" on the data-measurement flag, plus, optionally, the measured-vs-estimated count for one station. The integers are hundredths of a degree Celsius (2699 is 26.99 °C). The script does not convert them, and a month counts as estimated only when that flag is E. Don't point it at precipitation. Set STATION to any 11-character ID from NOAA's station list.

"""Count how much of NOAA's USHCN v2.5 final temperature data is estimated ("E" flag).

Flag meanings: https://www.ncei.noaa.gov/pub/data/ushcn/v2.5/readme.txt
"""
import tarfile
import urllib.request
from collections import defaultdict

URL = "https://www.ncei.noaa.gov/pub/data/ushcn/v2.5/ushcn.tavg.latest.FLs.52j.tar.gz"
STATION = None  # optional: an 11-character ID such as "USH00XXXXXX"
FIRST_YEAR = 2000


def parse_line(line):
    """Split one fixed-width USHCN line into (station, year, [(value, flag), ...])."""
    station = line[0:11]
    year = int(line[12:16])
    months = []
    for m in range(12):
        start = 16 + m * 9  # each month = 6-char value + 3 flag chars
        value = int(line[start:start + 6])  # hundredths of °C; -9999 = missing
        dm_flag = line[start + 6]  # DMFLAG only. "E" = estimated (two causes; see the readme)
        months.append((value, dm_flag))
    return station, year, months


def main():
    print("Downloading", URL)
    path, _ = urllib.request.urlretrieve(URL, "ushcn_tavg.tar.gz")

    total = defaultdict(int)  # year -> months with a value
    estimated = defaultdict(int)  # year -> months flagged "E"
    station_rows = []

    with tarfile.open(path) as tar:
        for member in tar.getmembers():
            if not member.isfile():
                continue
            for raw in tar.extractfile(member):
                station, year, months = parse_line(raw.decode("ascii"))
                if station == STATION:
                    station_rows.append((year, months))
                for value, flag in months:
                    if value == -9999:  # missing / not yet happened
                        continue
                    total[year] += 1
                    if flag == "E":
                        estimated[year] += 1

    print("\nShare of USHCN monthly values that are estimated ('E')")
    for year in sorted(y for y in total if y >= FIRST_YEAR):
        share = 100 * estimated[year] / total[year]
        print(f"  {year}: {share:5.1f}% ({estimated[year]} of {total[year]})")

    if not STATION:
        return
    print(f"\n{STATION}: months measured vs estimated")
    for year, months in sorted(station_rows):
        if year < FIRST_YEAR:
            continue
        real = sum(1 for v, f in months if v != -9999 and f != "E")
        est = sum(1 for v, f in months if v != -9999 and f == "E")
        print(f"  {year}: {real:2d} measured, {est:2d} estimated")


if __name__ == "__main__":
    main()

Save it as ushcn_estimates.py and run python ushcn_estimates.py. A station that has closed will show 0 measured months for every year since it closed.

Prefer not to run code? Pick a year or enter a station ID to see how many monthly values NOAA measured and how many it estimated on the USHCN estimate checker.

Sources