USAJobs Historical API Data

Data collection last run: 2025-08-27

⚠️ This is not an official USAJobs project

Resources

Dataset: 3,020,078 total job postings | Coverage: | Source: USAJobs Historical + Current APIs with field rationalization and deduplication

Table of Contents

Data Coverage by Year

Year Jobs Opened Jobs Closed Coverage Notes
201350Very limited
20142419Very limited
2015140131Very limited
20163,8791,633Very limited
2017237,145226,248✅ Complete year
2018328,111315,729✅ Complete year
2019349,256336,608✅ Complete year
2020327,545315,161✅ Complete year
2021369,151352,375✅ Complete year
2022441,604419,295✅ Complete year
2023454,652434,527✅ Complete year
2024367,755352,296✅ Complete year
2025140,811139,245Current through August 27, 2025

All Fields

Note: This table shows fields from historical jobs data. Current jobs API contains additional fields that are preserved in the original nested structure but not included in this rationalized view.

Field Type Examples Completeness
HiringPaths JSON Array [{"hiringPath": "Custom announcement"}], [{"hiringPath": "The public"}] (75896 unique combinations) 100%
JobCategories JSON Array [{"series": "0801"}, {"series": "1520"}, {"series": "1310"}, {"series": "1550"}, {"series": "1515"}], [{"series": "0855"}, {"series": "0150"}, {"series": "1301"}, {"series": "0801"}], [{"series": "0299"}], [{"series": "0830"}, {"series": "1301"}, {"series": "0801"}, {"series": "0819"}, {"series": "0806"}, {"series": "0190"}, {"series": "1350"}, {"series": "0408"}, {"series": "1310"}, {"series": "0150"}, {"series": "0850"}, {"series": "1320"}, {"series": "1315"}, {"series": "0810"}, {"series": "1313"}, {"series": "0808"}, {"series": "0401"}] (3060 unique) 100%
PositionLocations JSON Array [{"positionLocationCity": "Urbana", "positionLocationState": "Maryland", "positionLocationCountry": "United States"}, {"positionLocationCity": "Falls Church", "positionLocationState": "Virginia", "positionLocationCountry": "United States"}, {"positionLocationCity": "Woodlawn", "positionLocationState": "Maryland", "positionLocationCountry": "United States"}, {"positionLocationCity": "Baltimore", "positionLocationState": "Maryland", "positionLocationCountry": "United States"}, {"positionLocationCity": "Durham", "positionLocationState": "North Carolina", "positionLocationCountry": "United States"}, {"positionLocationCity": "Washington", "positionLocationState": "District of Columbia", "positionLocationCountry": "United States"}, {"positionLocationCity": "Alexandria", "positionLocationState": "Virginia", "positionLocationCountry": "United States"}, {"positionLocationCity": "Springfield", "positionLocationState": "Virginia", "positionLocationCountry": "United States"}, {"positionLocationCity": "Arlington", "positionLocationState": "Virginia", "positionLocationCountry": "United States"}], [{"positionLocationCity": "China Lake", "positionLocationState": "California", "positionLocationCountry": "United States"}] (26311 unique combinations) 100%
agencyLevel Integer 1, 2 100%
agencyLevelSort String Equal Employment Opportunity Commission, Department of Homeland Security\Cybersecurity and Infrastructure Security Agency, Department of Education\Immediate Office of the Secretary of Education, Department of the Army\U.S. Special Operations Command (Army) (542 unique) 100%
announcementClosingTypeCode String 01, 03, 02 100%
announcementClosingTypeDescription String Closing Date, Applicant Cut-Off, Open Continuous 100%
announcementNumber String WA-12303515-AR-24-127, 24-1948-SE-RF-D, JGDD244581289809HW, NIH-NICHD-DE-24-12480967 (363801 unique) 100%
appointmentType String Presidential Management Fellows, Recent graduates, ICTAP Only, Multiple (15 unique) 100%
disableApplyOnline String N, Y 100%
drugTestRequired String N 100%
hiringAgencyCode String DD04, AF0V, ARXB, GS14 (528 unique) 100%
hiringAgencyName String Commander, Navy Installations, National Technical Information Service, Office of the Secretary of Health and Human Services, Uniformed Services University of the Health Sciences (502 unique) 99%
hiringDepartmentCode String DJ, SM, ZV, SK (122 unique) 100%
hiringDepartmentName String Other Agencies and Independent Organizations, Department of Transportation, Department of Health and Human Services, Department of Justice (26 unique) 100%
hiringSubelementName String G4 - Camp Williams UT, AASF 2, Brooksville, FL, 816 SECURITY FORCES SQ, 859 Special Operations SQ (59973 unique) 62%
inserted_at String 2025-07-05T14:01:38.923692, 2025-07-05T14:18:59.530741, 2025-07-05T13:02:09.570063, 2025-07-05T13:55:05.422244 (367177 unique) 100%
maximumGrade String 12, 23, JJ, IJ (127 unique) 100%
maximumSalary Number $0, $105,612, $470,281 (range: $0-$470,281) (15671 unique) 100%
minimumGrade String LI, JH, 27, KK (125 unique) 100%
minimumSalary Number $0, $72,553, $400,000 (range: $0-$400,000) (15409 unique) 100%
payScale String ZA, DB, SZ, NV (191 unique) 100%
positionCloseDate String 2025-06-10, 2024-08-13, 2025-10-06, 2025-11-03 (672 unique) 100%
positionExpireDate String 2024-08-24, 2023-12-31, 2025-01-07, 2024-09-12 (550 unique) 9%
positionOpenDate String 2024-07-30, 2024-10-08, 2024-11-12, 2024-11-27 (365 unique) 100%
positionOpeningStatus String Applications under review, Job closed, Job canceled, Candidate selected (5 unique) 100%
positionTitle String Supervisory Licensed Professional Mental Health Counselor (HUD-VASH), Lead Government Information Specialist (NTE 1 YEAR, MBE up to 5 YRS, MBMP), PATIENT SAFETY MANAGER, Staff Psychologist-Psychotherapist (77986 unique) 100%
promotionPotential String 00, 06, 05, Note (115 unique) 100%
relocationExpensesReimbursed String N 100%
salaryType String Per Year, Per Hour, Without Compensation, Per Day (9 unique) 100%
securityClearance String Not Required, Secret, Other, L Access Authorization (8 unique) 100%
securityClearanceRequired String N, Y 100%
serviceType String Competitive, Excepted, Senior Executive 100%
supervisoryStatus String N, Y 100%
teleworkEligible String N 100%
totalOpenings String 221, 270, 125, 94 (157 unique) 90%
travelRequirement String Not required, Occasional travel, 25% or less, 75% or less (6 unique) 100%
usajobsControlNumber Integer 593449300, 693894500, 702096500 (367177 unique) 100%
usajobs_control_number String 593449300, 693894500, 702096500 (367177 unique) 100%
vendor String USASTAFFING, Monster - Hiring Management, FAA - SWIFT, HQMC MCCS (PeopleSoft) (8 unique) 100%
whoMayApply String Status Candidates (Merit Promotion and VEOA Eligibles) 0%
workSchedule String Full-time, Intermittent, Part-time, Multiple Schedules (6 unique) 100%

API Field Mapping & Normalization

This dataset combines data from two USAJobs APIs with field rationalization for consistent querying:

API Sources

Note: There is overlap between the APIs (2024-2025 jobs appear in both), but we collect from both APIs for completeness.

Important: The current_jobs_*.parquet files contain cumulative data - they include all jobs that have appeared in the Current API since we started collecting, not just jobs that are currently active. Once a job is added to these files, it remains there even after the position closes or is removed from the Current API. This provides a historical record of all jobs that were once "current."

Normalized Fields

Historical Field Name Historical API Source Current API Source Notes
usajobsControlNumber usajobsControlNumber Extracted from PositionURI Numeric job identifier
announcementNumber announcementNumber PositionID Public announcement ID
hiringAgencyName hiringAgencyName DepartmentName Agency name
hiringAgencyCode hiringAgencyCode OrganizationCodes (first part) Agency code
positionTitle positionTitle PositionTitle Job title
minimumGrade minimumGrade JobGrade[0].Code Minimum grade level
maximumGrade maximumGrade JobGrade[-1].Code Maximum grade level
minimumSalary minimumSalary PositionRemuneration[0].MinimumRange Minimum salary
maximumSalary maximumSalary PositionRemuneration[0].MaximumRange Maximum salary
positionOpenDate positionOpenDate PositionStartDate Position open date
positionCloseDate positionCloseDate PositionEndDate Position close date

Data Processing Approach

Data Structure

Code Examples from examples.py

The examples.py script demonstrates both local file access and direct GitHub downloads. It runs complete analysis on 2.97M job postings and automatically cleans up downloaded files.

Local Data Loading

import pandas as pd

# Load a single year
df_2024 = pd.read_parquet('data/historical_jobs_2024.parquet')
print(f"✓ Successfully loaded {len(df_2024):,} job postings from 2024")

GitHub Download Example

import pandas as pd
import requests

# Download directly from GitHub
url = 'https://github.com/abigailhaddad/usajobs_historical/raw/main/data/historical_jobs_2024.parquet'
df = pd.read_parquet(url)
print(f"✓ Downloaded {len(df):,} job postings")
Output:
✓ Successfully loaded 367,177 job postings from 2024
  Columns: 42
  Memory usage: 952.5 MB

Top Hiring Agencies Analysis

# 1. TOP 15 HIRING AGENCIES (2024 DATA)
top_agencies = df_2024['hiringAgencyName'].value_counts().head(15)
for i, (agency, count) in enumerate(top_agencies.items(), 1):
    percentage = count / len(df_2024) * 100
    print(f"{i:2d}. {agency}: {count:,} jobs ({percentage:.1f}%)")
Output:
1. Veterans Health Administration: 59,233 jobs (16.1%)
2. Army National Guard Units: 10,323 jobs (2.8%)
3. Commander, Navy Installations: 9,198 jobs (2.5%)
4. U.S. Army Corps of Engineers: 9,048 jobs (2.5%)
5. Military Treatment Facilities under DHA: 8,859 jobs (2.4%)
6. Army Installation Management Command: 8,526 jobs (2.3%)
7. U.S. Marine Corps: 7,971 jobs (2.2%)
8. Internal Revenue Service: 7,955 jobs (2.2%)
9. Justice, Bureau of Prisons/Federal Prison System: 6,993 jobs (1.9%)
10. National Park Service: 5,527 jobs (1.5%)

Salary Analysis

# Salary statistics
records_with_salary = df_2024[df_2024['maximumSalary'].notna()]
print(f"Records with salary data: {len(records_with_salary):,} ({len(records_with_salary)/len(df_2024)*100:.1f}%)")

# Salary ranges
min_range = f"${records_with_salary['minimumSalary'].min():,.0f} - ${records_with_salary['minimumSalary'].max():,.0f}"
max_range = f"${records_with_salary['maximumSalary'].min():,.0f} - ${records_with_salary['maximumSalary'].max():,.0f}"
median_range = f"${records_with_salary['minimumSalary'].median():,.0f} - ${records_with_salary['maximumSalary'].median():,.0f}"

print(f"Minimum salary range: {min_range}")
print(f"Maximum salary range: {max_range}")  
print(f"Median salary range: {median_range}")
Output:
Records with salary data: 367,177 (100.0%)
Minimum salary range: $0 - $400,000
Maximum salary range: $0 - $470,281
Median salary range: $72,553 - $105,612

Multi-Year Analysis with DuckDB

import duckdb

# Create DuckDB connection and register multiple Parquet files
conn = duckdb.connect('download/usajobs.duckdb')

# Register Parquet files as external tables
years = ['2022', '2023', '2024']
for year in years:
    file_path = f'data/historical_jobs_{year}.parquet'
    conn.execute(f"CREATE OR REPLACE VIEW jobs_{year} AS SELECT * FROM '{file_path}'")

# Create unified view
conn.execute("""
    CREATE OR REPLACE VIEW all_jobs AS 
    SELECT * FROM jobs_2024 
    UNION ALL SELECT * FROM jobs_2023 
    UNION ALL SELECT * FROM jobs_2022
""")

# Query salary trends by year
salary_trends = conn.execute("""
    SELECT 
        EXTRACT(year FROM positionOpenDate) as year,
        ROUND(AVG(minimumSalary)) as avg_min,
        ROUND(AVG(maximumSalary)) as avg_max,
        ROUND(percentile_cont(0.5) WITHIN GROUP (ORDER BY minimumSalary)) as median_min,
        ROUND(percentile_cont(0.5) WITHIN GROUP (ORDER BY maximumSalary)) as median_max,
        COUNT(*) as jobs
    FROM all_jobs 
    WHERE minimumSalary IS NOT NULL 
    GROUP BY EXTRACT(year FROM positionOpenDate)
    ORDER BY year DESC
""").fetchdf()

print(salary_trends)
Output:
Year | Avg Min | Avg Max | Median Min | Median Max | Jobs
-----|---------|---------|------------|------------|-----
2024 | $ 74222 | $104262 | $ 72553 | $ 105612 | 366772
2023 | $ 69048 | $ 97341 | $ 69107 | $ 93591 | 454348
2022 | $ 64748 | $ 91485 | $ 62926 | $ 88792 | 441351

Monthly Hiring Patterns

# Monthly posting patterns
monthly_posts = df_2024.groupby(df_2024['positionOpenDate'].dt.month).size()
print("Monthly posting patterns:")
month_names = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
for month, count in monthly_posts.items():
    percentage = count / len(df_2024) * 100
    print(f"    {month_names[month-1]}: {count:,} jobs ({percentage:.1f}%)")
Output:
Monthly posting patterns:
    Jan: 35,939 jobs (9.8%)
    Feb: 34,076 jobs (9.3%)
    Mar: 32,177 jobs (8.8%)
    Apr: 30,956 jobs (8.4%)
    May: 29,006 jobs (7.9%)
    Jun: 25,996 jobs (7.1%)
    Jul: 29,831 jobs (8.1%)
    Aug: 31,476 jobs (8.6%)
    Sep: 28,414 jobs (7.7%)
    Oct: 31,775 jobs (8.7%)
    Nov: 28,604 jobs (7.8%)
    Dec: 28,927 jobs (7.9%)

Most Common Position Titles

# Most common position titles
common_titles = df_2024['positionTitle'].value_counts().head(10)
print("Most common position titles:")
for i, (title, count) in enumerate(common_titles.items(), 1):
    percentage = count / len(df_2024) * 100
    print(f"   {i:2d}. {title}: {count:,} ({percentage:.1f}%)")
Output:
Most common position titles:
    1. Program Analyst: 3,324 (0.9%)
    2. Management and Program Analyst: 2,628 (0.7%)
    3. PROGRAM ANALYST: 2,203 (0.6%)
    4. Budget Analyst: 2,008 (0.5%)
    5. Administrative Officer: 1,817 (0.5%)
    6. Management Analyst: 1,606 (0.4%)
    7. Contract Specialist: 1,569 (0.4%)
    8. Logistics Management Specialist: 1,424 (0.4%)
    9. FINANCIAL MANAGEMENT ANALYST: 1,207 (0.3%)
    10. LOGISTICS MANAGEMENT SPECIALIST: 1,129 (0.3%)
Access: Download Parquet files from /data/ directory | Full examples: Run examples.py for complete analysis patterns | Source: Data collected from USAJobs.gov APIs