Purpose
Retrieve historical daily price records for a Barchart futures contract or supplied composite futures symbol, including displayed dates and available OHLCV or related fields.
When to Use
Use when the caller supplies an exact Barchart futures symbol such as CLU23 or an opaque composite/strategy symbol. The symbol must be supplied by the caller or obtained from an authoritative Barchart result; do not infer opaque symbols from their apparent leg structure.
Workflow
- Prefer Barchart's direct historical API. URL-encode the exact
{symbol}and construct this URL:https://www.barchart.com/proxies/core-api/v1/historical/get?symbol={encodeURIComponent(symbol)}&fields=tradeTime.format(m%2Fd%2FY)%2CopenPrice%2ChighPrice%2ClowPrice%2ClastPrice%2CpriceChange%2CpercentChange%2Cvolume%2CsymbolCode%2CsymbolType&type=eod&orderBy=tradeTime&orderDir=asc&limit=500&meta=field.shortName%2Cfield.type%2Cfield.description&raw=1 - In one browser call,
gotothat URL withwaitUntil: "domcontentloaded", then run thisevaluate()extractor on the API response page:
(() => {
const text = (document.body?.innerText || document.documentElement?.textContent || '').trim();
if (!text) return { headers: [], rows: [], raw: null };
let payload;
try { payload = JSON.parse(text); }
catch (error) { return { headers: [], rows: [], raw: text, error: 'Response was not JSON' }; }
const candidates = Array.isArray(payload)
? payload
: (Array.isArray(payload?.data) ? payload.data
: Array.isArray(payload?.results) ? payload.results
: Array.isArray(payload?.items) ? payload.items : []);
const rows = candidates.filter(row => row && typeof row === 'object' && !Array.isArray(row));
const headers = [...new Set(rows.flatMap(row => Object.keys(row)))];
return { headers, rows, rawKeys: payload && typeof payload === 'object' ? Object.keys(payload) : [] };
})()- Preserve the API's field names and values. The normal response includes formatted
tradeTime,openPrice,highPrice,lowPrice,lastPrice,priceChange,percentChange,volume,symbolCode, andsymbolType; do not assume every field is present for every instrument. - If the API response is unavailable or the caller specifically needs the visible table, use
https://www.barchart.com/futures/quotes/{contract-symbol}/price-history/historical, wait approximately 7–8 seconds afterdomcontentloaded, and run the table extractor below. For multiple supplied symbols, request each exact API URL or rendered history URL independently and join records on their displayed date; preserve only dates present in every leg.
Rendered-table fallback extractor:
(() => {
const clean = value => (value || '').replace(/\s+/g, ' ').trim();
const tables = [...document.querySelectorAll('table')];
const candidates = tables.map((table, index) => {
const rows = [...table.querySelectorAll('tr')];
if (!rows.length) return null;
const headerIndex = rows.findIndex(row => {
const text = clean(row.innerText).toLowerCase();
return /date/.test(text) && /open|high|low|close/.test(text);
});
if (headerIndex < 0) return null;
const headers = [...rows[headerIndex].querySelectorAll('th, td')].map(cell => clean(cell.innerText));
if (!headers.length) return null;
const data = rows.slice(headerIndex + 1).map(row =>
[...row.querySelectorAll('td, th')].map(cell => clean(cell.innerText))
).filter(values => values.length === headers.length && values.some(Boolean));
return { index, headers, rows: data };
}).filter(Boolean);
if (!candidates.length) return { headers: [], rows: [], tableIndex: null };
const best = candidates.sort((a, b) => b.rows.length - a.rows.length)[0];
return {
tableIndex: best.index,
headers: best.headers,
rows: best.rows.map(values => Object.fromEntries(best.headers.map((header, i) => [header || `column_${i + 1}`, values[i] ?? ''])))
};
})()Site-Specific Gotchas
- The direct API route is the shortest and most durable route for historical data. Its required parameters are
type=eod, ascendingtradeTimeordering,limit=500, the formatted trade-time field list, andraw=1. - URL-encode the exact supplied symbol as the
symbolquery value. Composite or spread-style symbols are opaque; preserve their complete form rather than parsing or guessing legs. - The API commonly returns records under
data, but the extractor also handlesresults,items, or a top-level array because response envelopes can vary. - The rendered history page is client-rendered. A short initial wait can produce no table; use the
Daily Pricesmarker or renderedMM/DD/YYYYdates as readiness indicators before retrying the same extractor. - A rendered page may contain unrelated layout tables. Select the table whose header contains
Dateand at least one OHLC field, not the first table. - For multi-contract calculations, independently obtain every exact supplied symbol, align on displayed date, exclude missing or nonnumeric values rather than treating them as zero, and only then calculate derived series such as
leg1 - 2 * leg2 + leg3.
Expected Output
For the preferred API route, return {headers, rows, rawKeys} where rows contains the API's dated historical records and headers is the union of returned field names. For the rendered fallback, return {tableIndex, headers, rows} with rows keyed by the page's column labels. For optional multi-contract analysis, additionally report the exact symbols, aligned date range, aligned observation count, and requested derived series or statistics.