DALL-E 2 86 (2022) and DALL-E 3 (2023) were announced for removal on 14 November 2025 and shut down on 12 May 2026, as the last output line above shows. Old tutorials break in three places:
Pass model explicitly. The API reference still says the default is dall-e-2, but the live API now answers a request without one with 400 Missing required parameter: 'model' (tested 26 Sep 2026).
DALL-E returned a temporary url; GPT Image 86 models always return b64_json.
quality: 'standard' | 'hd' and style give way to low to max; n goes up to 10 (DALL-E 3: 1) and prompts to 32,000 characters (DALL-E 3: 4,000).
<!doctype html>
<style>
body { margin: 0; padding: 8px; background: #fafaf7; font: 12px system-ui, sans-serif; color: #263238; max-width: 600px; }
.cols { display: flex; gap: 8px; }
pre { flex: 1; margin: 0; background: #fff; border: 1px solid #e0d8c8; padding: 6px; font-size: 11px; min-width: 0; white-space: pre-wrap; }
.del { background: #fbe3da; } .add { background: #d8eee2; }
svg { width: 100%; display: block; margin-top: 8px; }
</style>
<script src="https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js"></script>
<div class="cols">
<pre><b>2023 tutorial (DALL-E 3)</b>
<span class="del">(model omitted → dall-e-2)</span>
prompt: 'A bookshop cat',
<span class="del">quality: 'hd', style: 'vivid',</span>
<span class="del">n: 1, // DALL-E 3 max</span>
<span class="del">→ data[0].url (temporary link)</span></pre>
<pre><b>2026 (GPT Image)</b>
<span class="add">model: 'gpt-image-2.5-flare',</span>
prompt: 'A bookshop cat',
<span class="add">quality: 'low' … 'max',</span>
<span class="add">n: 4, // up to 10</span>
<span class="add">→ data[0].b64_json (always)</span></pre>
</div>
<p id="err" style="color:#b5452f"></p>
<svg viewBox="0 0 600 170" font-size="11"></svg>
<script>
// Without a model the live API answers 400 (tested 26 Sep 2026)
document.getElementById('err').textContent =
"Request without model → 400 Missing required parameter: 'model'. dall-e-3 → model shut down (12 May 2026).";
const limits = [
['images per request (n)', 1, 10],
['prompt length (characters)', 4000, 32000],
['quality levels', 2, 5],
];
const svg = d3.select('svg');
svg.append('text').attr('x', 0).attr('y', 12).attr('font-weight', 'bold').text('DALL-E 3 vs GPT Image limits (log scale)');
const x = d3.scaleLog([1, 40000], [180, 500]);
const y = d3.scaleBand(limits.map(l => l[0]), [24, 150]).padding(0.25);
svg.append('g').attr('transform', 'translate(0,150)').call(d3.axisBottom(x).ticks(5, '~s'));
const row = svg.selectAll('g.r').data(limits).join('g').attr('class', 'r').attr('transform', l => `translate(0,${y(l[0])})`);
row.append('text').attr('x', 172).attr('y', y.bandwidth() / 2).attr('dy', '0.35em').attr('text-anchor', 'end').text(l => l[0]);
[[1, '#b0bec5', 0], [2, '#3f7d3a', 0.5]].forEach(([k, color, dy]) => {
row.append('rect').attr('x', x(1)).attr('y', dy * y.bandwidth()).attr('height', y.bandwidth() / 2)
.attr('fill', color).attr('width', 0).transition().duration(800).attr('width', l => x(l[k]) - x(1));
row.append('text').attr('x', l => x(l[k]) + 4).attr('y', (dy + 0.25) * y.bandwidth()).attr('dy', '0.35em')
.text(l => `${l[k].toLocaleString()} ${k === 1 ? '(DALL-E 3)' : '(GPT Image)'}`);
});
</script>