1 2 3<!DOCTYPE html> 4<html lang="en"> 5<head> 6 <!-- Early theme detection to prevent flash of wrong theme. 7 Both attributes are set: data-theme is ours, data-bs-theme is what 8 Bootstrap 5.3 keys its own dark mode off, and the tokens feed both. --> 9
9<script> 10 (function() { 11 var theme = localStorage.getItem('theme') || 'light'; 12 document.documentElement.setAttribute('data-theme', theme); 13 document.documentElement.setAttribute('data-bs-theme', theme); 14 })(); 15 </script>
15 16 <!-- Cookie Consent by Osano --> 17 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css" /> 18
18<script src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js" data-cfasync="false"></script>
18 19
19<script> 20 window.addEventListener("load", function() { 21 // The consent library comes from a third party CDN and is a popular 22 // target for blocking extensions. If it is missing we must still serve 23 // adverts, non-personalised, rather than silently serving none. 24 if (!window.cookieconsent) { 25 loadAds(false); 26 return; 27 } 28 29 // Detect theme for cookie consent colors 30 var isDarkMode = document.documentElement.getAttribute('data-theme') === 'dark'; 31 var palette = isDarkMode ? { 32 // Dark mode: white popup to stand out 33 popup: { background: "#ffffff", text: "#1a1a1a" }, 34 button: { background: "#326690", text: "#ffffff" } 35 } : { 36 // Light mode: dark popup to stand out 37 popup: { background: "#1d1d1d", text: "#ffffff" }, 38 button: { background: "#326690", text: "#ffffff" } 39 }; 40 41 window.cookieconsent.initialise({ 42 palette: palette, 43 theme: "classic", 44 position: "bottom", 45 type: "opt-in", 46 content: { 47 message: "This website uses cookies to ensure you get the best experience and to help fund continued development.", 48 deny: "Decline", 49 allow: "Accept", 50 link: "Privacy Policy", 51 href: "/privacy_policy/" 52 }, 53 revokable: true, 54 onInitialise: function(status) { 55 var allowed = status === cookieconsent.status.allow; 56 if (allowed) { 57 loadAnalytics(); 58 } 59 // Adverts load either way; only the personalisation depends on 60 // consent. Previously nothing loaded at all until a visitor 61 // pressed Accept, so everyone who ignored the banner saw two 62 // empty rails and earned nothing. 63 loadAds(allowed); 64 }, 65 onStatusChange: function(status) { 66 if (status === cookieconsent.status.allow) { 67 loadAnalytics(); 68 // Ads already on the page cannot be upgraded in place; the 69 // next page view picks up personalisation. 70 loadAds(true); 71 } else { 72 // Disable analytics if declined 73 window['ga-disable-G-MKBV3S878F'] = true; 74 window.pgawebCookiesAllowed = false; 75 loadAds(false); 76 } 77 } 78 }); 79 }); 80 81 // Track consent state globally 82 window.pgawebCookiesAllowed = false; 83 84 function loadAnalytics() { 85 // Only load GA once 86 if (window.pgawebAnalyticsLoaded) return; 87 window.pgawebAnalyticsLoaded = true; 88 window.pgawebCookiesAllowed = true; 89 90 // Load Google Analytics 91 var script = document.createElement('script'); 92 script.async = true; 93 script.src = 'https://www.googletagmanager.com/gtag/js?id=G-MKBV3S878F'; 94 document.head.appendChild(script); 95 96 window.dataLayer = window.dataLayer || []; 97 function gtag(){dataLayer.push(arguments);} 98 window.gtag = gtag; 99 gtag('js', new Date()); 100 gtag('config', 'G-MKBV3S878F'); 101 } 102 103 var PGAWEB_AD_CLIENT = 'ca-pub-7509009547019933'; 104 105 /* 106 * Load the AdSense units. 107 * 108 * personalised: true once the visitor has accepted cookies, false when they 109 * have declined or have not yet chosen. Without consent we ask AdSense for 110 * non-personalised adverts, which earn less than personalised ones but a 111 * great deal more than the nothing we served before. 112 */ 113 function loadAds(personalised) { 114 // Only load ads once 115 if (window.pgawebAdsLoaded) return; 116 117 var adPlaceholders = document.querySelectorAll('.ad-placeholder'); 118 if (!adPlaceholders.length) return; 119 120 window.pgawebAdsLoaded = true; 121 122 window.adsbygoogle = window.adsbygoogle || []; 123 if (!personalised) { 124 // Must be set before the first push(). 125 window.adsbygoogle.requestNonPersonalizedAds = 1; 126 } 127 128 // The AdSense tag belongs on the page exactly once. It used to be 129 // appended inside the loop below, so a page with two rails loaded the 130 // whole library twice and re-initialised it over the filled slot. 131 var adScript = document.createElement('script'); 132 adScript.async = true; 133 adScript.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=' + 134 PGAWEB_AD_CLIENT; 135 adScript.crossOrigin = 'anonymous'; 136 document.head.appendChild(adScript); 137 138 // Determine if we're on mobile (below Bootstrap lg breakpoint). The unit 139 // is fixed once rendered, so this is decided at render time and not 140 // revisited. 141 var isMobile = window.innerWidth < 992; 142
143 adPlaceholders.forEach(function(placeholder) { 144 // Only fill placeholders that are actually rendered. The rails are 145 // hidden below the lg breakpoint and the inline unit is hidden above 146 // it, so on any given page one of the three is display:none. Pushing 147 // an advert into a zero-size container asks AdSense for an 148 // impression it cannot fill. 149 if (!placeholder.getClientRects().length) return; 150 151 // Each rail carries its own slot, so that they can be separate 152 // AdSense units and be told apart in reporting. 153 var slot = placeholder.getAttribute( 154 isMobile ? 'data-ad-slot-mobile' : 'data-ad-slot-desktop'); 155 if (!slot) return; 156 157 var ins = document.createElement('ins'); 158 ins.className = 'adsbygoogle'; 159 ins.setAttribute('data-ad-client', PGAWEB_AD_CLIENT); 160 ins.setAttribute('data-ad-slot', slot); 161 162 if (isMobile) { 163 // A fixed 320x100 large mobile banner rather than a responsive 164 // one, because the stylesheet reserves exactly that box and a 165 // known size means the advert arriving shifts nothing. The 166 // placeholder's own dimensions are deliberately left alone: this 167 // used to force it to 50px, which collapsed the 100px the css 168 // had reserved and moved the page under the reader. 169 ins.style.display = 'inline-block'; 170 ins.style.width = '320px'; 171 ins.style.height = '100px'; 172 } else { 173 // Fixed sizes rather than responsive, for the same reason the 174 // mobile unit is fixed: the reserved box and the advert are then 175 // the same size and nothing shifts. 176 // 177 // Responsive was tried and does not work here. A responsive unit 178 // takes its width from the element it is pushed into, and this 179 // element is a flex item in a centring container with no width 180 // of its own, so it measured zero and AdSense never filled
180it. 181 // 182 // Take the width from the rail itself rather than repeating 183 // _ads.scss's breakpoint here. The two cannot then disagree, and 184 // the rail is the thing that actually has to hold the advert. 185 var railWidth = Math.round(placeholder.getBoundingClientRect().width); 186 ins.style.display = 'inline-block'; 187 ins.style.width = (railWidth || 160) + 'px'; 188 ins.style.height = '600px'; 189 } 190 191 placeholder.appendChild(ins); 192 193 // Push the ad 194 window.adsbygoogle.push({}); 195 }); 196 } 197 </script>
197 198 <!-- End Cookie Consent --> 199 200 <!-- Template rendered: 1st October 2026 08:10:22 --> 201 <meta charset="utf-8"> 202 <meta name="viewport" content="width=device-width, initial-scale=1"> 203 <meta name="description" content="pgAdmin - PostgreSQL Tools for Windows, Mac, Linux and the Web"> 204 <link rel="icon" href="/static/COMPILED/assets/img/favicon.ico"> 205 206 <title>pgAdmin - PostgreSQL Tools</title> 207 208 <!-- 209 Inlined on purpose, and deliberately duplicated from _tokens.scss, 210 _shell.scss and _ads.scss. 211 212 The background stops a dark mode visitor getting a white flash before 213 the stylesheet arrives. The grid stops the page laying out full width and 214 then snapping into three columns: the shell and advert rules are chosen 215 by the critical css step, which concatenates whole templates and measures 216 against a 1300x900 fold, and page.html's markup necessarily lands after 217 base.html's closing tag and so below that fold. It therefore never 218 selects them, and they end up in the deferred stylesheet. 219 220 Keep this in step with those partials. It is a handful of rules, and the 221 alternative is layout shift on every page that has an advert rail. 222 --> 223 <style> 224 html[data-theme="dark"], html[data-theme="dark"] body { 225 background-color: #0d1117; 226 color: #e3e8ee; 227 } 228 .pga-shell { 229 display: grid; 230 grid-template-columns: 300px minmax(0, 1fr) 300px; 231 gap: 2rem; 232 max-width: 1720px; 233 margin-inline: auto; 234 padding: 2rem 1.25rem 3.5rem; 235 } 236 /* Explicit placement, so that a blocker hiding .ad-rail (EasyList 237 carries a generic rule for it) cannot let .pga-main auto place into 238 a rail track and render the page in a 300px column. See the longer 239 note in _shell.scss. Above lg only: the shell is one column below 240 it. */ 241 @media (min-width: 992px) { 242 .pga-shell > .ad-rail:first-child, 243 .pga-shell > .pga-doc-side { grid-column: 1; } 244 .pga-shell > .pga-main { grid-column: 2; } 245 .pga-shell > .ad-rail:last-child { grid-column: 3; } 246 } 247 .ad-placeholder { width: 300px; min-height: 600px; margin-inline: auto; } 248 /* Rails only: see the note in _ads.scss. The inline unit keeps its 249 reserved height so an arriving advert does not push the page. */ 250 .ad-rail .ad-placeholder:empty { min-height: 0; } 251 .pga-inline-ad { display: none; } 252 /* Which home page hero screenshot shows. Duplicated from _hero.scss so 253 that a dark visitor does not see the light one first; see the note 254 there. */ 255 .pga-hero-shot-dark { display: none; } 256 [data-bs-theme="dark"] .pga-hero-shot-light { display: none; } 257 [data-bs-theme="dark"] .pga-hero-shot-dark { display: block; } 258 @media (max-width: 1399.98px) { 259 .pga-shell { grid-template-columns: 160px minmax(0, 1fr) 160px; gap: 1.5rem; } 260 .ad-placeholder { width: 160px; } 261 } 262 @media (max-width: 991.98px) { 263 .pga-shell { grid-template-columns: minmax(0, 1fr); gap: 0; padding: 1.5rem 1rem 2.5rem; } 264 .ad-rail { display: none; } 265 .pga-inline-ad { display: block; } 266 .ad-placeholder { width: 320px; min-height: 100px; } 267 } 268 /* The 320x100 unit cannot shrink, so below 360px it breaks out of the 269 shell's padding rather than overflowing the page. */ 270 @media (max-width: 359.98px) { 271 .pga-inline-ad { margin-inline: -1rem; } 272 } 273 </style> 274 275 <link rel="stylesheet" href="/static/COMPILED/assets/css/main.css?e13d016a" /> 276 277
277<script> 278 var cb = function () { 279 var l = document.createElement('link'); 280 l.rel = 'stylesheet'; 281 l.href = '/static/COMPILED/assets/css/main_uncritical.css?e13d016a'; 282 /* 283 * Appended to the head, so that it comes after main.css in document 284 * order and therefore wins ties in the cascade. This used to insert 285 * the link *before* the head element, which put the deferred 286 * stylesheet ahead of the critical one: any rule of equal 287 * specificity in it silently lost. That is how the dark theme 288 * tokens were being beaten by the light ones, since the critical 289 * step puts :root in main.css and [data-bs-theme="dark"] in the 290 * deferred file. 291 */ 292 document.head.appendChild(l); 293 }; 294 var raf = requestAnimationFrame || mozRequestAnimationFrame || 295 webkitRequestAnimationFrame || msRequestAnimationFrame; 296 if (raf) raf(cb); 297 else window.addEventListener('load', cb); 298 </script>
298 299</head> 300<body> 301 302<header class="pga-nav"> 303 <div class="pga-nav-inner"> 304 <a class="pga-brand" href="/" aria-label="pgAdmin"> 305 <span class="pga-wordmark" aria-hidden="true"><!-- 306 The pgAdmin wordmark as the application itself draws it, taken from the 307 base64 data URI in web/pgadmin/static/js/AppMenuBar.jsx in pgadmin4 and 308 re-grouped so that the badge, the "pg" and the word can be coloured 309 separately. The app only ever draws this on a dark bar; the light scheme 310 needs the badge and the word inverted, which a single class cannot do. 311--> 312<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 205 50" role="img"> 313<title>pgAdmin</title> 314<path class="pga-mark-badge" d="M58.94,41.4a2.48,2.48,0,0,1-2.27-3.49L64,21.29V6a6,6,0,0,0-6-6H6A6,6,0,0,0,0,6V44a6,6,0,0,0,6,6H58a6,6,0,0,0,6-6V41.4Z"/> 315<path class="pga-mark-pg" d="M29.25,30.17a13.13,13.13,0,0,1-1.82-6.93,13,13,0,0,1,1.82-6.88,12.5,12.5,0,0,1,1.48-1.95,10.44,10.44,0,0,0-3.25-2.89,11.16,11.16,0,0,0-5.65-1.45q-4.48,0-6.72,2.64V10.44H7.51V40.36a1,1,0,0,0,1,1h6a1,1,0,0,0,1-1V31.19a8.47,8.47,0,0,0,6.34,2.4,11.26,11.26,0,0,0,5.65-1.45,10.53,10.53,0,0,0,2.06-1.56C29.44,30.44,29.34,30.31,29.25,30.17ZM23.6,25.8a4.52,4.52,0,0,1-3.45,1.44,4.48,4.48,0,0,1-3.44-1.44,5.6,5.6,0,0,1-1.35-4,5.59,5.59,0,0,1,1.35-4,4.46,4.46,0,0,1,3.44-1.45,4.49,4.49,0,0,1,3.45,1.45,5.63,5.63,0,0,1,1.34,4A5.64,5.64,0,0,1,23.6,25.8Z"/><path class="pga-mark-pg" d="M56.49,12.63V31.24q0,6.35-3.44,9.51t-9.92,3.17a25.42,25.42,0,0,1-6.3-.75,15,15,0,0,1-5-2.23l2.89-5.59a10.17,10.17,0,0,0,3.51,1.79,14.37,14.37,0,0,0,4.18.65A6.53,6.53,0,0,0,47,36.4a5.37,5.37,0,0,0,1.47-4.11v-.76c-1.54,1.8-3.79,2.69-6.76,2.69a11.7,11.7,0,0,1-5.59-1.36A10.37,10.37,0,0,1,32.09,29a10.89,10.89,0,0,1-1.51-5.77,10.86,10.86,0,0,1,1.51-5.74,10.42,10.42,0,0,1,4.07-3.86,11.71,11.71,0,0,1,5.59-1.37c3.25,0,5.63,1.06,7.14,3.15V12.63Zm-9.3,13.95a4.4,4.4,0,0,0,1.4-3.36,4.34,4.34,0,0,0-1.38-3.34,5.65,5.65,0,0,0-7.16,0,4.3,4.3,0,0,0-1.41,3.34,4.35,4.35,0,0,0,1.43,3.36,5.08,5.08,0,0,0,3.57,1.3A5,5,0,0,0,47.19,26.58Z"/> 316<path class="pga-mark-word" d="M83.43,32.89H71l-2,5.09a1,1,0,0,1-.93.62H61.73a1,1,0,0,1-.91-1.4L72.91,9.8a1,1,0,0,1,.92-.6h6.89a1,1,0,0,1,.91.6L93.77,37.2a1,1,0,0,1-.92,1.4H86.41a1,1,0,0,1-.93-.62ZM81,26.76l-3.78-9.41-3.78,9.41Z"/><path class="pga-mark-word" d="M120.44,8.44V37.6a1,1,0,0,1-1,1h-5.6a1,1,0,0,1-1-1V36.33Q110.62,39,106.16,39a11.29,11.29,0,0,1-5.67-1.45,10.54,10.54,0,0,1-4-4.14A12.62,12.62,0,0,1,95,27.18,12.53,12.53,0,0,1,96.44,21a10.35,10.35,0,0,1,4-4.09,11.48,11.48,0,0,1,5.67-1.43,8.24,8.24,0,0,1,6.3,2.35V8.44a1,1,0,0,1,1-1h6A1,1,0,0,1,120.44,8.44Zm-9.19,22.75a5.71,5.71,0,0,0,1.34-4,5.6,5.6,0,0,0-1.32-3.95,4.47,4.47,0,0,0-3.43-1.43,4.53,4.53,0,0,0-3.44,1.43,5.51,5.51,0,0,0-1.34,3.95,5.67,5.67,0,0,0,1.34,4,4.77,4.77,0,0,0,6.85,0Z"/><path class="pga-mark-word" d="M161,18c1.66,1.68,2.5,4.21,2.5,7.6v12a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V26.88a5.67,5.67,0,0,0-.9-3.53,3.09,3.09,0,0,0-2.55-1.13,3.62,3.62,0,0,0-2.89,1.26,5.71,5.71,0,0,0-1.1,3.82V37.6a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V26.88c0-3.11-1.14-4.66-3.44-4.66a3.7,3.7,0,0,0-2.94,1.26,5.71,5.71,0,0,0-1.09,3.82V37.6a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V16.84a1,1,0,0,1,1-1h5.6a1,1,0,0,1,1,1v1.39a8,8,0,0,1,3-2.08,10.23,10.23,0,0,1,3.8-.69,10,10,0,0,1,4.29.88A7.28,7.28,0,0,1,146.42,19a8.85,8.85,0,0,1,3.41-2.65,10.93,10.93,0,0,1,4.49-.92A9,9,0,0,1,161,18Z"/><path class="pga-mark-word" d="M168.12,12.1a3.91,3.91,0,0,1-1.34-2.79A4.16,4.16,0,0,1,168,6.19a5,5,0,0,1,3.67-1.36A5.25,5.25,0,0,1,175.18,6a3.75,3.75,0,0,1,1.34,3,4.1,4.1,0,0,1-1.34,3.13,5.68,5.68,0,0,1-7.06,0Zm.54,3.74h6a1,1,0,0,1,1,1V37.6a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V16.84A1,1,0,0,1,168.66,15.84Z"/><path class="pga-mark-word" d="M201.55,18q2.59,2.52,2.59,7.6v12a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V26.88q0-4.66-3.74-4.66a4.3,4.3,0,0,0-3.3,1.34,5.83,5.83,0,0,0-1.24,4v10a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V16.84a1,1,0,0,1,1-1h5.61a1,1,0,0,1,1,1v1.47a9.05,9.05,0,0,1,3.19-2.12,10.78,10.78,0,0,1,4-.73A9.34,9.34,0,0,1,201.55,18Z"/> 317</svg> 318</span> 319 </a> 320 321 <ul class="pga-nav-links"> 322 <li> 323 <a href="/features/" 324 >Features</a> 325 </li> 326 <li class="dropdown"> 327 <a href="/docs/" class="dropdown-toggle" 328 data-bs-toggle="dropdown" role="button" aria-expanded="false">Docs</a> 329 <div class="dropdown-menu"> 330 <a class="dropdown-item" href="/docs/">Documentation home</a> 331 <div class="dropdown-divider"></div> 332 333 334 <h6 class="dropdown-header">pgAdmin 4</h6> 335 336 <a class="dropdown-item" 337 href="/docs/pgadmin4/9.18/index.html">Version 9.18</a> 338 339 <a class="dropdown-item" 340 href="/docs/pgadmin4/9.17/index.html">Version 9.17</a> 341 342 <a class="dropdown-item" 343 href="/docs/pgadmin4/9.16/index.html">Version 9.16</a> 344 345 <a class="dropdown-item" 346 href="/docs/pgadmin4/development/index.html">Development</a> 347 348 349 </div> 350 </li> 351 <li> 352 <a href="/community/" 353 >Community</a> 354 </li> 355 <li> 356 <a href="/development/" 357 >Development</a> 358 </li> 359 </ul> 360 361 362 <form class="pga-search" id="search_form" action="/search/" method="get"> 363 <label for="search_q" class="visually-hidden">Search docs</label> 364 <i class="fas fa-search" aria-hidden="true"></i> 365 <input id="search_q" name="q" type="search" 366 placeholder="Search docs"> 367 368 </form> 369 370 <div class="pga-nav-tools"> 371 <button class="pga-nav-toggle" type="button" data-nav-toggle 372 aria-label="Menu" aria-expanded="false"> 373 <i class="fas fa-bars" aria-hidden="true"></i> 374 </button> 375 376 <button class="pga-icon-btn" id="theme-toggle" type="button" 377 aria-label="Toggle dark mode" title="Toggle dark mode"> 378 <i class="fas fa-moon" id="theme-icon" aria-hidden="true"></i> 379 </button> 380 381 <a class="pga-icon-btn" href="https://github.com/pgadmin-org/pgadmin4" 382 target="_blank" rel="noopener" aria-label="pgAdmin on GitHub" title="View on GitHub"> 383 <i class="fab fa-github" aria-hidden="true"></i> 384 </a> 385 386 <a class="pga-btn pga-btn-primary pga-btn-sm" href="/download/"> 387 <i class="fas fa-download" aria-hidden="true"></i>
388 <span class="pga-btn-label">Download</span> 389 </a> 390 </div> 391 </div> 392</header> 393 394 395 396 397<section class="pga-hero"> 398 <div class="pga-hero-inner"> 399 <div> 400 <span class="pga-eyebrow">pgadmin 4 · v9.18</span> 401 <h1>The PostgreSQL management tool</h1> 402 <p class="pga-lead">Administration, development and monitoring for PostgreSQL. 403 Desktop or server mode, on Windows, macOS, Linux and in containers. Open 404 source, and maintained by the people who use it.</p> 405 406 <div class="pga-hero-actions"> 407 <a class="pga-btn pga-btn-primary" href="/download/"> 408 <i class="fas fa-download" aria-hidden="true"></i> Download 9.18</a> 409 <a class="pga-btn" href="/docs/pgadmin4/latest/index.html">Documentation</a> 410 <a class="pga-btn" href="https://github.com/pgadmin-org/pgadmin4" 411 target="_blank" rel="noopener"><i class="fab fa-github" aria-hidden="true"></i> Source</a> 412 </div> 413 414 415 <div class="pga-terminal" data-mode="download"> 416 <div class="pga-terminal-bar"> 417 <span class="pga-terminal-lights" aria-hidden="true"><span></span><span></span><span></span></span> 418 <span class="pga-terminal-title">Install pgAdmin</span> 419 </div> 420 <div class="pga-terminal-head"> 421 <div class="pga-terminal-tabs" role="tablist" aria-label="Installation method"> 422 <button role="tab" class="active" data-install="windows" aria-selected="true"><i class="fab fa-windows" aria-hidden="true"></i> Windows</button> 423 <button role="tab" data-install="macos" aria-selected="false"><i class="fab fa-apple" aria-hidden="true"></i> macOS</button> 424 <button role="tab" data-install="container" aria-selected="false"><i class="fab fa-docker" aria-hidden="true"></i> Container</button> 425 <button role="tab" data-install="deb" aria-selected="false"><i class="fab fa-ubuntu" aria-hidden="true"></i> DEB</button> 426 <button role="tab" data-install="rpm" aria-selected="false"><i class="fab fa-redhat" aria-hidden="true"></i> RPM</button> 427 <button role="tab" data-install="pip" aria-selected="false"><i class="fab fa-python" aria-hidden="true"></i> pip</button> 428 </div> 429 <button class="pga-terminal-copy" type="button" data-copy> 430 <i class="far fa-copy" aria-hidden="true"></i> copy</button> 431 </div> 432 433 434 <div class="pga-install-panel pga-install-get" data-install-panel="windows"> 435 <p>A signed installer for Windows, covering both desktop and server mode. 436 Requires a 64-bit version of Windows.</p> 437 <a class="pga-btn" href="/download/pgadmin-4-windows/"> 438 <i class="fas fa-download" aria-hidden="true"></i>
438 Windows installers</a> 439 </div> 440 441 442 <div class="pga-install-panel pga-install-get" data-install-panel="macos" hidden> 443 <p>A signed and notarised disk image for macOS, built as a universal 444 binary for Apple silicon and Intel.</p> 445 <a class="pga-btn" href="/download/pgadmin-4-macos/"> 446 <i class="fas fa-download" aria-hidden="true"></i> macOS disk images</a> 447 </div> 448 449<pre class="pga-install-panel" data-install-panel="container" hidden><span class="c"># Pull and run the container image</span> 450<span class="p">$</span> docker pull dpage/pgadmin4 451<span class="p">$</span> docker run -p <span class="s">80:80</span> \ 452 -e <span class="s">'[email protected]'</span> \ 453 -e <span class="s">'PGADMIN_DEFAULT_PASSWORD=SuperSecret'</span> \ 454 -d dpage/pgadmin4 455</pre> 456 457<pre class="pga-install-panel" data-install-panel="deb" hidden><span class="c"># Install the signing key and the repository</span> 458<span class="p">$</span> curl -fsS <span class="s">https://www.pgadmin.org/static/packages_pgadmin_org.pub</span> | sudo gpg --dearmor -o /etc/apt/keyrings/packages-pgadmin-org.gpg 459<span class="p">$</span> sudo sh -c <span class="s">'echo "deb [signed-by=/etc/apt/keyrings/packages-pgadmin-org.gpg] https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main" > /etc/apt/sources.list.d/pgadmin4.list && apt update'</span> 460 461<span class="p">$</span> sudo apt install pgadmin4 <span class="c"># desktop and web</span> 462<span class="p">$</span> sudo apt install pgadmin4-desktop <span class="c"># desktop only</span> 463<span class="p">$</span> sudo apt install pgadmin4-web <span class="c"># web only</span> 464</pre> 465 466<pre class="pga-install-panel" data-install-panel="rpm" hidden><span class="c"># Set up the repository (Fedora)</span> 467<span class="p">$</span> sudo rpm -i <span class="s">https://ftp.postgresql.org/pub/pgadmin/pgadmin4/yum/pgadmin4-fedora-repo-2-1.noarch.rpm</span> 468 469<span class="c"># ...or AlmaLinux, Rocky, RHEL and CentOS</span> 470<span class="p">$</span> sudo rpm -i <span class="s">https://ftp.postgresql.org/pub/pgadmin/pgadmin4/yum/pgadmin4-redhat-repo-2-1.noarch.rpm</span> 471 472<span class="p">$</span> sudo yum install pgadmin4 <span class="c"># desktop and web</span> 473<span class="p">$</span> sudo yum install pgadmin4-desktop <span class="c"># desktop only</span> 474<span class="p">$</span> sudo yum install pgadmin4-web <span class="c"># web only</span> 475</pre> 476 477<pre class="pga-install-panel" data-install-panel="pip" hidden><span class="c"># Create the data and log directories</span> 478<span class="p">$</span> sudo mkdir /var/lib/pgadmin 479<span class="p">$</span> sudo mkdir /var/log/pgadmin 480<span class="p">$</span> sudo chown $USER /var/lib/pgadmin 481<span class="p">$</span> sudo chown $USER /var/log/pgadmin 482 483<span class="c"># Install and run in a virtual environment</span> 484<span class="p">$</span> python3 -m venv pgadmin4 485<span class="p">$</span> source pgadmin4/bin/activate 486<span class="p">(pgadmin4) $</span> pip install pgadmin4 487<span class="p">(pgadmin4) $</span> pgadmin4 488</pre> 489 </div> 490 491 <div class="pga-platforms"> 492 <span class="pga-chip"><i class="fas fa-scale-balanced" aria-hidden="true"></i> PostgreSQL licence</span> 493 <span class="pga-chip"><i class="fas fa-rotate" aria-hidden="true"></i> Released roughly every six weeks</span> 494 <span class="pga-chip"><i class="fas fa-language" aria-hidden="true"></i> Translated by the community</span> 495 </div> 496 </div> 497 498 <div> 499 500 <picture class="pga-hero-shot-light"> 501 <source type="image/webp" srcset="/static/COMPILED/assets/img/screenshot-light.webp?e13d016a"> 502 <img class="pga-hero-shot" src="/static/COMPILED/assets/img/screenshot-light.png?e13d016a" 503 alt="pgAdmin 4 showing the properties of a table, over the server dashboard" 504 width="1591" height="1068"> 505 </picture> 506 <picture class="pga-hero-shot-dark"> 507 <source type="image/webp" srcset="/static/COMPILED/assets/img/screenshot-dark.webp?e13d016a"> 508 <img class="pga-hero-shot" src="/static/COMPILED/assets/img/screenshot-dark.png?e13d016a" 509 alt="pgAdmin 4 showing the properties of a table, over the server dashboard" 510 width="1591" height="1068" loading="lazy"> 511 </picture> 512 </div> 513 </div> 514</section> 515 516 517<main class="pga-shell"> 518 519 <aside class="ad-rail" aria-label="Advertisement"> 520 <div class="pga-rail-inner"> 521 522<div class="ad-placeholder" 523 data-ad-slot-desktop="4641019325" 524 data-ad-slot-mobile="3787987132" 525 aria-hidden="true"></div> 526 527 </div> 528 </aside> 529 530 <div class="pga-main"> 531 532 <div class="pga-inline-ad"> 533 534<div class="ad-placeholder" 535 data-ad-slot-desktop="4641019325" 536 data-ad-slot-mobile="3787987132" 537 aria-hidden="true"></div> 538 539 </div> 540 541 542 543<section class="pga-section"> 544 <div class="pga-section-head"> 545 <div>
546 <span class="pga-eyebrow">why pgadmin</span> 547 <h2>Everything PostgreSQL, in one place</h2> 548 </div> 549 <a class="pga-btn pga-btn-sm" href="/features/">All features 550 <i class="fas fa-arrow-right" aria-hidden="true"></i></a> 551 </div> 552 <div class="pga-grid-3"> 553 <article class="pga-card"> 554 <i class="fas fa-laptop-code pga-card-icon" aria-hidden="true"></i> 555 <h3>Cross-platform</h3> 556 <p>Run it on Windows, macOS or Linux as a desktop application, or deploy it 557 as a web application reachable from any browser.</p> 558 </article> 559 <article class="pga-card"> 560 <i class="fas fa-database pga-card-icon" aria-hidden="true"></i> 561 <h3>Complete object management</h3> 562 <p>Create, browse and maintain every PostgreSQL object through a graphical 563 interface that keeps the generated SQL in plain sight.</p> 564 </article> 565 <article class="pga-card"> 566 <i class="fas fa-code pga-card-icon" aria-hidden="true"></i> 567 <h3>A serious query tool</h3> 568 <p>Syntax highlighting, auto-completion, query history and a graphical 569 EXPLAIN for working out where the time actually goes.</p> 570 </article> 571 </div> 572</section> 573 574 575<section class="pga-section"> 576 <div class="pga-section-head"> 577 <div> 578 <span class="pga-eyebrow">watch</span> 579 <h2>Latest videos</h2> 580 </div> 581 <a class="pga-btn pga-btn-sm" href="/videos/">All videos 582 <i class="fas fa-arrow-right" aria-hidden="true"></i></a> 583 </div> 584 <div class="pga-grid-3"> 585 586 <article class="pga-media-card"> 587 <div class="pga-thumb pga-thumb-video"> 588 <iframe src="https://www.youtube-nocookie.com/embed/OftuG2VaT0I" 589 title="Video: How to use Restore Dialog in pgAdmin 4" frameborder="0" loading="lazy" 590 allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 591 referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> 592 </div> 593 <span class="pga-meta">Oct. 23, 2023 · Nikhil Mohite, EDB</span> 594 <h3>How to use Restore Dialog in pgAdmin 4</h3> 595 </article> 596 597 <article class="pga-media-card"> 598 <div class="pga-thumb pga-thumb-video"> 599 <iframe src="https://www.youtube-nocookie.com/embed/ZaynFa9rGtY" 600 title="Video: Authenticate pgAdmin 4 with Github" frameborder="0" loading="lazy" 601 allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 602 referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> 603 </div> 604 <span class="pga-meta">Sept. 1, 2023 · Yogesh Mahajan, EDB</span> 605 <h3>Authenticate pgAdmin 4 with Github</h3> 606 </article> 607 608 <article class="pga-media-card"> 609 <div class="pga-thumb pga-thumb-video"> 610 <iframe src="https://www.youtube-nocookie.com/embed/Z2-V0THRyY0" 611 title="Video: Kerberos and Active Directory setup in pgAdmin 4" frameborder="0" loading="lazy" 612 allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 613 referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> 614 </div> 615 <span class="pga-meta">Aug. 23, 2023 · Khushboo Vashi, EDB</span> 616 <h3>Kerberos and Active Directory setup in pgAdmin 4</h3> 617 </article> 618 619 </div> 620</section> 621 622 623 624<section class="pga-section"> 625 <div class="pga-section-head"> 626 <div> 627 <span class="pga-eyebrow">read</span> 628 <h2>From the blogs</h2> 629 </div> 630 <a class="pga-btn pga-btn-sm" href="/blogs/">All posts 631 <i class="fas fa-arrow-right" aria-hidden="true"></i></a> 632 </div> 633 <div class="pga-grid-3"> 634 635 <article class="pga-media-card">
636 <span class="pga-meta">March 16, 2026 · Dave Page</span> 637 <h3>AI Features in pgAdmin: AI Insights for EXPLAIN Plans</h3> 638 <p class="pga-card-text">This is the third and final post in a series covering the new AI functionality in pgAdmin 4. In the first post, I covered LLM configuration and the …</p> 639 <a class="pga-card-link" href="https://www.pgedge.com/blog/ai-features-in-pgadmin-ai-insights-for-explain-plans" target="_blank" rel="noopener"> 640 Read the post <i class="fas fa-external-link-alt fa-xs" aria-hidden="true"></i></a> 641 </article> 642 643 <article class="pga-media-card"> 644 <span class="pga-meta">March 10, 2026 · Dave Page</span> 645 <h3>AI Features in pgAdmin: The AI Chat Agent</h3> 646 <p class="pga-card-text">This is the second in a series of three blog posts covering the new AI functionality in pgAdmin 4. In the first post, I covered LLM configuration and …</p> 647 <a class="pga-card-link" href="https://www.pgedge.com/blog/ai-features-in-pgadmin-the-ai-chat-agent" target="_blank" rel="noopener"> 648 Read the post <i class="fas fa-external-link-alt fa-xs" aria-hidden="true"></i></a> 649 </article> 650 651 <article class="pga-media-card"> 652 <span class="pga-meta">March 9, 2026 · Dave Page</span> 653 <h3>AI Features in pgAdmin: Configuration and Reports</h3> 654 <p class="pga-card-text">This is the first in a series of three blog posts covering the new AI functionality coming in pgAdmin 4. In this post, I'll walk through how to …</p> 655 <a class="pga-card-link" href="https://www.pgedge.com/blog/ai-features-in-pgadmin-configuration-and-reports" target="_blank" rel="noopener"> 656 Read the post <i class="fas fa-external-link-alt fa-xs" aria-hidden="true"></i></a> 657 </article> 658 659 </div> 660</section> 661 662 663 664<section class="pga-section"> 665 <div class="pga-section-head"> 666 <div> 667 <span class="pga-eyebrow">announcements</span> 668 <h2>Recent news</h2> 669 </div> 670 <a class="pga-btn pga-btn-sm" href="/news/">News archive 671 <i class="fas fa-arrow-right" aria-hidden="true"></i></a> 672 </div> 673 674 <article class="pga-news-item"> 675 <span class="pga-meta">Sept. 17, 2026</span> 676 <div> 677 <h3>pgAdmin 4 v9.18 Released</h3> 678 <div class="pga-news-body"><p>The pgAdmin Development Team is pleased to announce the release of pgAdmin 4 version 9.18. This release of pgAdmin 4 includes 29 bug fixes and new features, including fixes for four security vulnerabilities (CVE-2026-86861 through CVE-2026-86864). For more details, please see the <a href="https://www.pgadmin.org/docs/pgadmin4/9.18/release_notes_9_18.html">release notes</a>.</p> 679 680<p>pgAdmin is the leading open-source graphical management tool for PostgreSQL. For more information, please see <a href="https://www.pgadmin.org/">the website</a>.</p> 681 682<p>Notable changes in this release include:</p> 683 684<h2>Features:</h2> 685 686<ul> 687 <li>Collapse and restore the Object Explorer by re-clicking the current workspace icon, in the manner of the VS Code side bar, remembering the choice across refreshes. A keyboard shortcut, <code>Ctrl+Alt+B</code> by default, does the same thing and can be changed through the new <code>toggle_object_explorer</code> preference.</li> 688 <li>Harden the default Content-Security-Policy so inline scripts run under a per-request nonce rather than a blanket <code>'unsafe-inline'</code>, and drop <code>'unsafe-eval'</code>. <code>style-src</code> keeps <code>'unsafe-inline'</code>, because MUI and React inject runtime styles and inline <code>style</code> attributes that cannot carry a nonce, and development bundles have <code>'unsafe-eval'</code> re-added automatically when <code>DEBUG</code> is set.</li> 689</ul> 690 691<h2>Security Fixes:</h2> 692 693<ul> 694 <li>Fix an authentication bypass in Webserver authentication mode, where <code>get_user()</code> fell back to reading the configured <code>WEBSERVER_REMOTE_USER</code> name from the inbound request headers when it was absent from the WSGI environment. Because a header is written by whoever sends the request, any client that could reach pgAdmin could assert any identity, including an administrator's, without presenting a credential. A header-asserted identity is now opt-in, restricted to a configured list of trusted proxies with an optional shared secret, and refused for accounts whose authentication source is not <code>webserver</code> (CVE-2026-86863).</li> 695 <li>Fix argument and connection-string injection in the Backup tool, where the client-supplied database name was appended to the <code>pg_dump</code> argument vector as a bare positional value. Because <code>getopt_long</code> permutes arguments, a value beginning with a dash supplied further options such as <code>--file</code>, overriding the storage-confined output path; and because libpq expands a database name containing an equals sign into a full connection string, the same field could redirect the connection, and the password exported in <code>PGPASSWORD</code>, to a host of the caller's choosing. The database name is now passed through the <code>PGDATABASE</code> environment variable, which libpq never expands (CVE-2026-86864).</li> 696 <li>Fix connection-string injection in the Restore and Maintenance tools, where the client-supplied database name was passed straight to <code>--dbname</code> and could likewise redirect the connection, and the exported password, to a server of the caller's choosing (CVE-2026-86862).</li> 697 <li>Fix a time-of-check to time-of-use flaw in the File Manager's <code>save_file</code> endpoint, which backs saving from the Query Tool and ERD: the requested path was validated with <code>check_access_permission()</code> and then opened with a plain <code>open()</code>, so a symbolic link planted in between was followed, writing outside the user's storage directory. This is the write sink that CVE-2026-7819's hardening of the separate upload path did not cover (CVE-2026-86861).</li> 698 <li>Refuse HTTP redirects on LLM API requests, rather than following a <code>Location</code> header on to a destination the <code>ALLOWED_LLM_API_URLS</code> check was never applied to. This is hardening rather than a fix for an exploitable flaw, since returning the redirect at all requires control of a host already on the allowlist.</li> 699 <li>Reject an empty or null <code>Username</code> when importing a non-shared server, which previously imported cleanly and left a server that libpq would silently authenticate as the OS account running pgAdmin rather than reject outright.</li> 700</ul> 701 702<h2>Bugs/Housekeeping:</h2> 703 704<ul> 705 <li>Fix login being impossible against Flask-Security-Too 5.8.2, which corrected a long-standing inversion in <code>UserMixin.is_locked()</code> that pgAdmin's own <code>is_locked()</code> had been written against.</li> 706 <li>Fix inherited columns in the Table dialog being editable and deletable, and the Data type dropdown on the exp
706anded Definition tab offering every type rather than honouring the allowed-type restriction applied inline.</li> 707 <li>Reinstate dependency ordering of the script Schema Diff generates, which had been lost since the React port left <code>dependLevel</code> unset.</li> 708 <li>Fix Schema Diff reporting false differences for SERIAL and BIGSERIAL columns, duplicating any column that also differs when recreating a foreign table, losing a foreign table column's collation, injecting whitespace into an applied function or procedure body, generating SQL that PostgreSQL rejects when a sequence's MINVALUE is raised above its current value, and reporting a comparison that fails part way through as a success.</li> 709 <li>Share concurrent identical GET requests behind <code>getNodeAjaxOptions()</code> so a wide table's Columns tab no longer fires one duplicate <code>get_types</code> request per column row.</li> 710 <li>Fix the argument grid on the Definition tab of a user-defined function or procedure refusing to delete, or add, a row in edit mode.</li> 711 <li>Omit the redundant <code>TABLESPACE pg_default</code> clause from generated index SQL, which was invalid on a partitioned table.</li> 712 <li>Fix a crash when a per-server Password Exec Command is used with a service-only (<code>pg_service.conf</code>) connection, which leaves host, port and username unset.</li> 713 <li>Accept <code>SharedUsername</code> when importing a shared server from a <code>servers.json</code> definition, instead of insisting on <code>Username</code> for every server.</li> 714 <li>Render the Validate binary path dialog as HTML, instead of showing the raw markup.</li> 715 <li>Remove a trailing quote from the Windows installer's <code>ProductVersion</code>, and fix the <code>existingSecret</code> path in the Helm deployment template.</li> 716 <li>Skip importing and initialising the Kerberos, LDAP, MFA, OAuth2 and Webserver authentication providers unless <code>SERVER_MODE</code> is set, leaving desktop mode with internal authentication alone.</li> 717 <li>Bump JavaScript and Python third-party dependencies, and update the message catalogs, including a fix for the Korean catalog that had not been recompiled since November 2025.</li> 718</ul> 719 720<p>Builds for Windows and macOS are available now, along with a Python Wheel, Docker Container, RPM, DEB Package, and source code tarball from the <a href="https://www.pgadmin.org/download/">download area</a>.</p></div> 721 </div> 722 </article> 723 724 <article class="pga-news-item"> 725 <span class="pga-meta">July 31, 2026</span> 726 <div> 727 <h3>pgAdmin 4 v9.17 Released</h3> 728 <div class="pga-news-body"><p>The pgAdmin Development Team is pleased to announce the release of pgAdmin 4 version 9.17. This release of pgAdmin 4 includes 28 bug fixes and new features, including fixes for seven security vulnerabilities (CVE-2026-17346 through CVE-2026-17351, and CVE-2026-17566). For more details, please see the <a href="https://www.pgadmin.org/docs/pgadmin4/9.17/release_notes_9_17.html">release notes</a>.</p> 729 730<p>pgAdmin is the leading open-source graphical management tool for PostgreSQL. For more information, please see <a href="https://www.pgadmin.org/">the website</a>.</p> 731 732<p>Notable changes in this release include:</p> 733 734<h2>Features:</h2> 735 736<ul> 737 <li>Include the authenticated user's identity in the HTTP access log.</li> 738 <li>Add an opt-in Gateway API <code>HTTPRoute</code> template to the Helm chart as an alternative to the existing Ingress.</li> 739 <li>Add a preference to cap the row count fetched by the plain "View Data" action, so it is usable on large tables without always doing a full <code>SELECT *</code>.</li> 740 <li>Add support for a custom XYZ tile provider (URL, name, CRS, attribution, max zoom) in the Geometry Viewer, alongside the existing built-in base layers.</li> 741</ul> 742 743<h2>Security Fixes:</h2> 744 745<ul> 746 <li>Fix a tool-permission bypass where a user denied the Query Tool, Grant Wizard, or Schema Diff permission could still drive that tool's backend routes and Socket.IO handlers directly, since the permission check was applied only to a
746single "front door" route per tool. Also fixes a non-owner triggering an adhoc connection against another user's shared server persisting a new server record still owned by that other user (CVE-2026-17350).</li> 747 <li>Fix OS command injection in the <code>MASTER_PASSWORD_HOOK</code> feature, where an externally-sourced username (e.g. via OAuth2/OIDC, Kerberos, or webserver authentication) containing shell metacharacters could execute arbitrary commands as the pgAdmin service account when the configured hook string uses <code>%u</code> (CVE-2026-17347).</li> 748 <li>Fix a lexer-differential bypass of the AI Assistant's read-only transaction guard, where sqlparse's string-literal lexing disagreed with PostgreSQL's own parser under <code>standard_conforming_strings = on</code>, letting a crafted multi-statement payload smuggle a <code>COMMIT</code> past the intended read-only wrapper; an incomplete fix for CVE-2026-12045 (CVE-2026-17351).</li> 749 <li>Fix SQL injection in the Index Statistics all-indexes listing and the Publications/Subscriptions Dependencies views, where an apostrophe in a table, index, publication, or subscription name broke out of an unescaped template interpolation; an incomplete fix for CVE-2026-12044 (CVE-2026-17346).</li> 750 <li>Fix several Constraints, Preferences, Debugger, and Schema Diff routes missing the <code>@pga_login_required</code> decorator, making them reachable without authentication in server mode; an incomplete fix for CVE-2026-12046 (CVE-2026-17348).</li> 751 <li>Fix an adhoc server connection cloning another user's stored database credentials (password, save password flag, tunnel password) alongside ownership, letting a non-owner who cloned another user's shared server connect using that user's saved database password (CVE-2026-17349).</li> 752 <li>Fix OS command injection in the Import/Export Data tool, where a query-based export could pass a crafted query string past the <code>\copy (...)</code> parenthesis-balance guard by exploiting a backslash-escape mismatch with psql's default <code>standard_conforming_strings = on</code> behaviour, exposing a live <code>TO PROGRAM</code> clause for arbitrary command execution (CVE-2026-17566).</li> 753</ul> 754 755<h2>Bugs/Housekeeping:</h2> 756 757<ul> 758 <li>Fix Schema Diff's "Generate Script" and the browser tree's CREATE Script view emitting wrong SQL for SERIAL/identity columns, by detecting column-owned sequences via <code>pg_depend</code> instead of guessing the sequence name.</li> 759 <li>Fix ALT+F5 ("Execute query at cursor") doing nothing when the cursor is on or near a statement that is not highlighted, in a Query Tool tab with multiple statements separated by blank lines.</li> 760 <li>Fix the object browser's extension UI breaking under PostgreSQL 19's extension catalog changes.</li> 761 <li>Detect a selected-but-unusable OS keyring and fall back gracefully instead of failing.</li> 762 <li>Warn when OAuth2 provider settings are misplaced at the top level of the config instead of under <code>OAUTH2_CONFIG</code>.</li> 763 <li>Honor the selected EOL sequence when copying query text to the clipboard.</li> 764 <li>Fix a Schema Diff result-status filter chip showing "No difference found" after being toggled off and back on, even when real differences exist.</li> 765 <li>Fix the Object Explorer briefly showing literal HTML markup instead of a greyed-out "[Disconnecting...]" label when disconnecting a server or database.</li> 766 <li>Centralize shared-server-group visibility and access-control logic, and adjust the ServerGroup-to-Server/SharedServer model relationships.</li> 767 <li>Fail the macOS appbundle build if any bundled library links outside the bundle, and scan all Mach-O binaries for bundle linkage.</li> 768 <li>Pin the sonarqube-scan-action GitHub workflow to a full commit SHA, and pin the Yarn version used by the build scripts to the <code>packageManager</code> field.</li> 769 <li>Bump JavaScript and Python third-party dependencies, including axios, webpack, react, electron, and certifi.</li> 770 <li>Update the Simplified Chinese (zh_Hans_CN) translation.</li> 771</ul> 772 773<p>Builds for Windows and macOS are available now, along with a Python Wheel, Docker Container, RPM, DEB Package, and source code tarball from the <a href="https://www.pgadmin.org/download/">download area</a>.</p></div> 774 </div> 775 </article> 776 777 <article class="pga-news-item">
778 <span class="pga-meta">June 18, 2026</span> 779 <div> 780 <h3>pgAdmin 4 v9.16 Released</h3> 781 <div class="pga-news-body"><p>The pgAdmin Development Team is pleased to announce the release of pgAdmin 4 version 9.16. This release of pgAdmin 4 includes 64 bug fixes and new features, including fixes for seven security vulnerabilities (CVE-2026-12044 through CVE-2026-12050). For more details, please see the <a href="https://www.pgadmin.org/docs/pgadmin4/9.16/release_notes_9_16.html">release notes</a>.</p> 782 783<p>pgAdmin is the leading open-source graphical management tool for PostgreSQL. For more information, please see <a href="https://www.pgadmin.org/">the website</a>.</p> 784 785<p>Notable changes in this release include:</p> 786 787<h2>Features:</h2> 788 789<ul> 790 <li>Colorize panel and tab headers based on the connected server's colour, making it easier to identify which server a tab belongs to at a glance.</li> 791 <li>Add a "Back to login" link to the Forgot Password and Reset Password pages.</li> 792 <li>Add support for the TOAST tuple target storage parameter in the Materialized View dialog.</li> 793 <li>Make the init container security context in the Helm chart configurable via <code>containerSecurityContext</code>.</li> 794 <li>Add support for closing a tab with a middle-click on its title.</li> 795 <li>Allow the OAuth2 login button icon to use any Font Awesome style, not only brand icons.</li> 796</ul> 797 798<h2>Security Fixes:</h2> 799 800<ul> 801 <li>Fix SQL injection across sixteen dialog templates that rendered <code>COMMENT ON ... IS '<description>'</code>; switches affected templates to <code>qtLiteral</code> and rewrites stats calls to pass the relation OID via a <code>::oid::regclass</code> cast (CVE-2026-12044).</li> 802 <li>Fix an AI Assistant read-only transaction bypass that allowed prompt-injected multi-statement payloads to commit out of the <code>READ ONLY</code> wrapper, chaining to RCE via <code>COPY ... TO PROGRAM</code> on a superuser connection (CVE-2026-12045).</li> 803 <li>Fix two SQL Editor endpoints missing the <code>@pga_login_required</code> decorator, making them reachable without authentication in server mode and exposing a pickle deserialization sink (CVE-2026-12046).</li> 804 <li>Fix HTML injection in the cloud deployment module (RDS, Azure, Google) where SDK exception text was forwarded to the browser unsanitised and rendered through <code>html-react-parser</code> (CVE-2026-12047).</li> 805 <li>Fix critical stored cross-site scripting where PostgreSQL server error text and Explain plan-node content passed through <code>html-react-parser</code> across notifier toasts, form errors, modal alerts, and the Explain visualiser; injected script could exfiltrate saved server credentials and issue SQL against every connected server (CVE-2026-12048).</li> 806 <li>Fix an open redirect in the multi-factor authentication flow via an unvalidated <code>next</code> parameter (CVE-2026-12049).</li> 807 <li>Fix SQL injection in the named restore point endpoint where the user-supplied restore point name was interpolated into SQL via <code>str.format()</code> instead of a bound parameter (CVE-2026-12050).</li> 808</ul> 809 810<h2>Bugs/Housekeeping:</h2> 811 812<ul> 813 <li>Remove the administrator-role bypass from server-access helpers so the access-control checks added in 9.15 (CVE-2026-7813) are enforced uniformly.</li> 814 <li>Remove EDB BigAnimal cloud deployment support, which was deprecated in 9.15.</li> 815 <li>Preserve <code>jsonb</code> number representation in the JSON editor so trailing fractional zeros and large integers are no longer rewritten when saving unmodified rows.</li> 816 <li>Fix a View/Edit Data crash when the session contains a transaction object that is not filter-capable, which could prevent the desktop application from loading after an upgrade.</li> 817 <li>Rebase version-specific SQL templates so the default targets PostgreSQL 14, the oldest supported server version, dropping obsolete sub-14 template buckets.</li> 818 <li>Strip the foreign-architecture slice from the macOS bundle so single-arch builds no longer ship unused code.</li> 819 <li>Bump Electron to 42.3.3, <code>cryptography</code> to 49.0, and other Python and JavaScript dependencies.</li> 820 <li>Update the Italian translation.</li> 821</ul> 822 823<h2>Deprecations:</h2> 824 825<ul> 826 <li><strong>
826pgAgent</strong> has been deprecated and will be discontinued. pgAgent will be removed from the website within one month, and support within pgAdmin will be removed approximately six months from now. Users are encouraged to migrate to an alternative job scheduling solution.</li> 827</ul> 828 829<p>Builds for Windows and macOS are available now, along with a Python Wheel, Docker Container, RPM, DEB Package, and source code tarball from the <a href="https://www.pgadmin.org/download/">download area</a>.</p></div> 830 </div> 831 </article> 832 833</section> 834 835 836 837<div class="pga-version-strip"> 838 <div> 839 <span class="pga-eyebrow">current release</span> 840 <strong>pgAdmin 4 v9.18</strong> 841 </div> 842 <a class="pga-btn pga-btn-primary" href="/download/"> 843 <i class="fas fa-download" aria-hidden="true"></i> Download</a> 844</div> 845 846 847 848 849 <div class="pga-inline-ad"> 850 851<div class="ad-placeholder" 852 data-ad-slot-desktop="5411175511" 853 data-ad-slot-mobile="2474905464" 854 aria-hidden="true"></div> 855 856 </div> 857 </div> 858 859 <aside class="ad-rail" aria-label="Advertisement"> 860 <div class="pga-rail-inner"> 861 862<div class="ad-placeholder" 863 data-ad-slot-desktop="5411175511" 864 data-ad-slot-mobile="2474905464" 865 aria-hidden="true"></div> 866 867 </div> 868 </aside> 869 870</main> 871 872 873<footer class="pga-footer"> 874 <div class="pga-footer-inner"> 875 <div> 876 <a class="pga-brand" href="/" aria-label="pgAdmin"> 877 <span class="pga-wordmark" aria-hidden="true"><!-- 878 The pgAdmin wordmark as the application itself draws it, taken from the 879 base64 data URI in web/pgadmin/static/js/AppMenuBar.jsx in pgadmin4 and 880 re-grouped so that the badge, the "pg" and the word can be coloured 881 separately. The app only ever draws this on a dark bar; the light scheme 882 needs the badge and the word inverted, which a single class cannot do. 883--> 884<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 205 50" role="img"> 885<title>pgAdmin</title> 886<path class="pga-mark-badge" d="M58.94,41.4a2.48,2.48,0,0,1-2.27-3.49L64,21.29V6a6,6,0,0,0-6-6H6A6,6,0,0,0,0,6V44a6,6,0,0,0,6,6H58a6,6,0,0,0,6-6V41.4Z"/> 887<path class="pga-mark-pg" d="M29.25,30.17a13.13,13.13,0,0,1-1.82-6.93,13,13,0,0,1,1.82-6.88,12.5,12.5,0,0,1,1.48-1.95,10.44,10.44,0,0,0-3.25-2.89,11.16,11.16,0,0,0-5.65-1.45q-4.48,0-6.72,2.64V10.44H7.51V40.36a1,1,0,0,0,1,1h6a1,1,0,0,0,1-1V31.19a8.47,8.47,0,0,0,6.34,2.4,11.26,11.26,0,0,0,5.65-1.45,10.53,10.53,0,0,0,2.06-1.56C29.44,30.44,29.34,30.31,29.25,30.17ZM23.6,25.8a4.52,4.52,0,0,1-3.45,1.44,4.48,4.48,0,0,1-3.44-1.44,5.6,5.6,0,0,1-1.35-4,5.59,5.59,0,0,1,1.35-4,4.46,4.46,0,0,1,3.44-1.45,4.49,4.49,0,0,1,3.45,1.45,5.63,5.63,0,0,1,1.34,4A5.64,5.64,0,0,1,23.6,25.8Z"/><path class="pga-mark-pg" d="M56.49,12.63V31.24q0,6.35-3.44,9.51t-9.92,3.17a25.42,25.42,0,0,1-6.3-.75,15,15,0,0,1-5-2.23l2.89-5.59a10.17,10.17,0,0,0,3.51,1.79,14.37,14.37,0,0,0,4.18.65A6.53,6.53,0,0,0,47,36.4a5.37,5.37,0,0,0,1.47-4.11v-.76c-1.54,1.8-3.79,2.69-6.76,2.69a11.7,11.7,0,0,1-5.59-1.36A10.37,10.37,0,0,1,32.09,29a10.89,10.89,0,0,1-1.51-5.77,10.86,10.86,0,0,1,1.51-5.74,10.42,10.42,0,0,1,4.07-3.86,11.71,11.71,0,0,1,5.59-1.37c3.25,0,5.63,1.06,7.14,3.15V12.63Zm-9.3,13.95a4.4,4.4,0,0,0,1.4-3.36,4.34,4.34,0,0,0-1.38-3.34,5.65,5.65,0,0,0-7.16,0,4.3,4.3,0,0,0-1.41,3.34,4.35,4.35,0,0,0,1.43,3.36,5.08,5.08,0,0,0,3.57,1.3A5,5,0,0,0,47.19,26.58Z"/> 888<path class="pga-mark-word" d="M83.43,32.89H71l-2,5.09a1,1,0,0,1-.93.62H61.73a1,1,0,0,1-.91-1.4L72.91,9.8a1,1,0,0,1,.92-.6h6.89a1,1,0,0,1,.91.6L93.77,37.2a1,1,0,0,1-.92,1.4H86.41a1,1,0,0,1-.93-.62ZM81,26.76l-3.78-9.41-3.78,9.41Z"/><path class="pga-mark-word" d="M120.44,8.44V37.6a1,1,0,0,1-1,1h-5.6a1,1,0,0,1-1-1V36.33Q110.62,39,106.16,39a11.29,11.29,0,0,1-5.67-1.45,10.54,10.54,0,0,1-4-4.14A12.62,12.62,0,0,1,95,27.18,12.53,12.53,0,0,1,96.44,21a10.35,10.35,0,0,1,4-4.09,11.48,11.48,0,0,1,5.67-1.43,8.24,8.24,0,0,1,6.3,2.35V8.44a1,1,0,0,1,1-1h6A1,1,0,0,1,120.44,8.44Zm-9.19,22.75a5.71,5.71,0,0,0,1.34-4,5.6,5.6,0,0,0-1.32-3.95,4.47,4.47,0,0,0-3.43-1.43,4.53,4.53,0,0,0-3.44,1.43,5.51,5.51,0,0,0-1.34,3.95,5.67,5.67,0,0,0,1.34,4,4.77,4.77,0,0,0,6.85,0Z"/><path class="pga-mark-word" d="M161,18c1.66,1.68,2.5,4.21,2.5,7.6v12a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V26.88a
8885.67,5.67,0,0,0-.9-3.53,3.09,3.09,0,0,0-2.55-1.13,3.62,3.62,0,0,0-2.89,1.26,5.71,5.71,0,0,0-1.1,3.82V37.6a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V26.88c0-3.11-1.14-4.66-3.44-4.66a3.7,3.7,0,0,0-2.94,1.26,5.71,5.71,0,0,0-1.09,3.82V37.6a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V16.84a1,1,0,0,1,1-1h5.6a1,1,0,0,1,1,1v1.39a8,8,0,0,1,3-2.08,10.23,10.23,0,0,1,3.8-.69,10,10,0,0,1,4.29.88A7.28,7.28,0,0,1,146.42,19a8.85,8.85,0,0,1,3.41-2.65,10.93,10.93,0,0,1,4.49-.92A9,9,0,0,1,161,18Z"/><path class="pga-mark-word" d="M168.12,12.1a3.91,3.91,0,0,1-1.34-2.79A4.16,4.16,0,0,1,168,6.19a5,5,0,0,1,3.67-1.36A5.25,5.25,0,0,1,175.18,6a3.75,3.75,0,0,1,1.34,3,4.1,4.1,0,0,1-1.34,3.13,5.68,5.68,0,0,1-7.06,0Zm.54,3.74h6a1,1,0,0,1,1,1V37.6a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V16.84A1,1,0,0,1,168.66,15.84Z"/><path class="pga-mark-word" d="M201.55,18q2.59,2.52,2.59,7.6v12a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V26.88q0-4.66-3.74-4.66a4.3,4.3,0,0,0-3.3,1.34,5.83,5.83,0,0,0-1.24,4v10a1,1,0,0,1-1,1h-6a1,1,0,0,1-1-1V16.84a1,1,0,0,1,1-1h5.61a1,1,0,0,1,1,1v1.47a9.05,9.05,0,0,1,3.19-2.12,10.78,10.78,0,0,1,4-.73A9.34,9.34,0,0,1,201.55,18Z"/> 889</svg> 890</span> 891 </a> 892 <p class="pga-footer-blurb">The most popular and feature-rich open source 893 administration and development platform for PostgreSQL, the most advanced 894 open source database in the world.</p> 895 </div> 896 <div> 897 <h2>Product</h2> 898 <ul> 899 <li><a href="/features/">Features</a></li> 900 <li><a href="/features/#screenshots">Screenshots</a></li> 901 <li><a href="/download/">Download</a></li> 902 <li><a href="/docs/pgadmin4/latest/index.html">Documentation</a></li> 903 </ul> 904 </div> 905 <div> 906 <h2>Community</h2> 907 <ul> 908 <li><a href="/community/">Getting help</a></li> 909 <li><a href="/community/#list">Mailing list</a></li> 910 <li><a href="/community/#issues">Issue tracker</a></li> 911 <li><a href="/security/">Security advisories</a></li> 912 <li><a href="/news/">News archive</a></li> 913 </ul> 914 </div> 915 <div> 916 <h2>Development</h2> 917 <ul> 918 <li><a href="/development/#contributing">Contributing</a></li> 919 <li><a href="/development/#resources">Resources</a></li> 920 <li><a href="/development/#translations">Translations</a></li> 921 <li><a href="/development/team/">Team</a></li> 922 <li><a href="/styleguide/typography/">Style guide</a></li> 923 </ul> 924 </div> 925 <div> 926 <h2>About</h2> 927 <ul> 928 <li><a href="/faq/">FAQ</a></li> 929 <li><a href="/licence/">Licence</a></li> 930 <li><a href="/privacy_policy/">Privacy policy</a></li> 931 <li><a href="#" onclick="document.querySelector('.cc-revoke').click(); return false;">Cookie settings</a></li> 932 </ul> 933 </div> 934 </div> 935 <div class="pga-colophon"> 936 <span>© 2026 pgAdmin Development Team</span> 937 <span>Postgres, PostgreSQL and the Slonik logo are trademarks or registered 938 trademarks of the 939 <a href="https://www.postgres.ca">PostgreSQL Community Association of Canada</a>.</span> 940 </div> 941</footer> 942 943 944
945<script src="/static/COMPILED/webp.js?e13d016a"></script>
vendor: 1 bytes, line 945
945
946<script src="/static/COMPILED/main.js?e13d016a"></script>
946 947
948<script> 949 /* Theme toggle. Sets both attributes: data-theme drives our tokens, 950 data-bs-theme drives Bootstrap's own components. */ 951 (function() { 952 var toggle = document.getElementById('theme-toggle'); 953 var html = document.documentElement; 954 if (!toggle) { return; } 955 956 function apply(theme) { 957 html.setAttribute('data-theme', theme); 958 html.setAttribute('data-bs-theme', theme); 959 /* Font Awesome's SVG+JS replaces the <i> with an <svg>, so the icon 960 has to be swapped by replacing the element rather than its class. */ 961 var current = toggle.querySelector('i, svg'); 962 if (current) { 963 var icon = document.createElement('i'); 964 icon.id = 'theme-icon'; 965 icon.setAttribute('aria-hidden', 'true'); 966 icon.className = theme === 'dark' ? 'fas fa-sun' : 'fas fa-moon'; 967 current.replaceWith(icon); 968 } 969 } 970 971 apply(localStorage.getItem('theme') || 'light'); 972 973 toggle.addEventListener('click', function() { 974 var next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'; 975 localStorage.setItem('theme', next); 976 apply(next); 977 }); 978 })(); 979 980 /* Collapsed navigation below the lg breakpoint. */ 981 (function() { 982 document.querySelectorAll('[data-nav-toggle]').forEach(function(btn) { 983 btn.addEventListener('click', function() { 984 var inner = btn.closest('.pga-nav-inner'); 985 if (!inner) { return; } 986 var open = inner.classList.toggle('open'); 987 btn.setAttribute('aria-expanded', open ? 'true' : 'false'); 988 }); 989 }); 990 })(); 991</script>
991 992 993
994<script> 995/* Install method tabs. */ 996function selectInstall(box, name) { 997 var found = false; 998 box.querySelectorAll('.pga-terminal-tabs button').forEach(function (b) { 999 var match = b.getAttribute('data-install') === name; 1000 if (match) { found = true; } 1001 b.classList.toggle('active', match); 1002 b.setAttribute('aria-selected', match ? 'true' : 'false'); 1003 }); 1004 if (!found) { return false; } 1005 1006 var active = null; 1007 box.querySelectorAll('.pga-install-panel').forEach(function (p) { 1008 p.hidden = p.getAttribute('data-install-panel') !== name; 1009 if (!p.hidden) { active = p; } 1010 }); 1011 /* Nothing to copy when the panel is an installer download. */ 1012 box.setAttribute('data-mode', 1013 active && active.tagName === 'PRE' ? 'commands' : 'download'); 1014 return true; 1015} 1016 1017document.querySelectorAll('.pga-terminal-tabs button').forEach(function (btn) { 1018 btn.addEventListener('click', function () { 1019 selectInstall(btn.closest('.pga-terminal'), 1020 btn.getAttribute('data-install')); 1021 }); 1022}); 1023 1024/* 1025 * Open on the tab for the visitor's own platform, so the common case is the 1026 * command they actually need rather than one they have to go looking for. 1027 * 1028 * userAgentData.platform is the modern, unspoofed source and is checked first; 1029 * navigator.platform is deprecated but is all Firefox and Safari offer, and the 1030 * user agent string is the last resort. Windows stays the markup default, so a 1031 * browser that answers none of these is no worse off. 1032 * 1033 * Linux is deliberately not mapped to a package format. Nothing in the browser 1034 * distinguishes a Debian derivative from a Red Hat one, and guessing wrong puts 1035 * a Fedora user in front of an apt command; the container instructions work 1036 * everywhere, so that is where an unrecognised Linux lands. 1037 */ 1038(function () { 1039 var box = document.querySelector('.pga-hero .pga-terminal'); 1040 if (!box) { return; } 1041 1042 var uaData = navigator.userAgentData; 1043 var platform = (uaData && uaData.platform) || navigator.platform || ''; 1044 var ua = navigator.userAgent || ''; 1045 var haystack = (platform + ' ' + ua).toLowerCase(); 1046 1047 var name = null; 1048 if (haystack.indexOf('win') !== -1) { 1049 name = 'windows'; 1050 } else if (haystack.indexOf('mac') !== -1 || haystack.indexOf('iphone') !== -1 || 1051 haystack.indexOf('ipad') !== -1) { 1052 name = 'macos'; 1053 } else if (haystack.indexOf('linux') !== -1 || haystack.indexOf('android') !== -1 || 1054 haystack.indexOf('cros') !== -1) { 1055 name = 'container'; 1056 } 1057 1058 if (name) { selectInstall(box, name); } 1059})(); 1060 1061/* Copy the commands from whichever panel is showing, without the prompt. */ 1062document.querySelectorAll('[data-copy]').forEach(function (btn) { 1063 btn.addEventListener('click', function () { 1064 var pre = btn.closest('.pga-terminal') 1065 .querySelector('pre.pga-install-panel:not([hidden])'); 1066 if (!pre || !navigator.clipboard) { return; } 1067 var text = pre.innerText.split('\n').map(function (line) { 1068 return line.replace(/^(\(pgadmin4\) )?\$ /, ''); 1069 }).join('\n'); 1070 navigator.clipboard.writeText(text).then(function () { 1071 var was = btn.innerHTML; 1072 btn.innerHTML = '<i class="fas fa-check"></i> copied'; 1073 setTimeout(function () { btn.innerHTML = was; }, 1500); 1074 }); 1075 }); 1076}); 1077</script>
1077 1078 1079 1080</body> 1081</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.