PFMA Reveals

PFMA Reveals UK’s Most Popular Pets This Year

PFMA: The UK’s Most Popular Pets This Year | BuyAPet.co.uk
PFMA Insights

PFMA Reveals UK’s Most Popular Pets This Year

From pups and moggies to fish, bunnies and bearded dragons—here’s a friendly walkthrough of what Brits are choosing, why it’s shifting, and how to pick the right companion for your home.

5-minute read UK Focus Welfare-led

At a glance

PFMA’s latest UK Pet Population insights show dogs & cats leading the way, with strong interest in small mammals and aquatics.

Dogs Cats Fish Small Mammals Birds Reptiles

Dogs still top the table

Brits remain devoted to dogs—family-friendly, active lifestyles and workplace flexibility keep demand strong.

Cats thrive in urban homes

Compact living and indoor enrichment make cats a natural fit for flats and city life.

Small pets & aquatics grow

First-time owners explore fish and small mammals for gentler space and care requirements.

What the PFMA findings mean for owners

Time & activity

  • Dogs: daily exercise and training; consider breed energy levels.
  • Cats: enrichment, scratching posts, safe outdoor access if possible.
  • Small mammals: bigger habitats than you think; gentle handling.
  • Fish: cycle tanks, stable water quality, species compatibility.

Budget & planning

  • Set aside monthly funds for food, insurance and routine vet care.
  • Plan for enrichment: toys, habitats, perches and replacements.
  • Emergency cushion for unexpected treatment.

Regional notes

Urban areas lean towards cats, small mammals and aquatics, while suburban and rural households show higher dog ownership and outdoor-friendly breeds.

Trend watch

  • Welfare-first choices and better matching of lifestyles to breeds/species.
  • Ongoing interest in adoption and rehoming.
  • Owners seek cost-smart enrichment and preventive care.

Picking the right pet for your home

Space & routine

Match species to your daily rhythm. High-energy dogs need time outside; cats and small mammals can thrive in smaller spaces with enrichment.

Experience level

First pet? Consider temperaments known for patience, or start with easier-care species and build confidence.

Future-proofing

Think about lifespan, family changes and housing plans so your pet’s needs are met for the long term.

PFMA FAQs

What is the PFMA and why is its report trusted?

The Pet Food Manufacturers’ Association collates national pet ownership data and industry input to build the annual UK Pet Population view used by vets, rescues and policymakers.


Which pets are most popular right now?

Dogs and cats lead UK households overall. Fish, small mammals, birds and reptiles follow with steady ownership across different lifestyles.


Is there a best first pet for families?

There’s no single “best” pet—only the best fit. Consider time, budget, allergies, and space. Meet animals in person and talk to vets or rescue advisors.


Should I adopt or buy from a breeder?

Adoption is a brilliant, ethical option. If buying, choose responsible breeders who prioritise health testing, socialisation and lifelong support.


How do costs compare between species?

Dogs and cats generally cost more monthly than small mammals or fish due to food, insurance and routine care. Costs vary by breed/size and setup.

Information based on PFMA UK pet ownership insights and everyday best practice in welfare-led ownership. Always consider your household’s needs and speak with your vet.

Visit this page
'; const bottom = document.createElement('div'); bottom.className = 'bap-v7-ui-bottom'; bottom.innerHTML = '
Please enter your card number, expiry date and CVC above.
' + ''; fieldset.insertBefore(top, fieldset.firstChild); fieldset.appendChild(bottom); top.querySelector('.bap-v7-close').addEventListener('click', closeModal); bottom.querySelector('.bap-v7-continue').addEventListener('click', closeModal); } function neutraliseAncestors(fieldset) { neutralisedAncestors = []; let parent = fieldset.parentElement; while (parent && parent !== document.body && parent !== document.documentElement) { parent.classList.add('bap-stripe-v7-neutralise'); neutralisedAncestors.push(parent); parent = parent.parentElement; } } function restoreAncestors() { neutralisedAncestors.forEach(function (element) { if (element && element.classList) { element.classList.remove('bap-stripe-v7-neutralise'); } }); neutralisedAncestors = []; } function freezePage() { const html = document.documentElement; const body = document.body; savedScrollY = window.pageYOffset || html.scrollTop || body.scrollTop || 0; oldBodyPosition = body.style.position; oldBodyTop = body.style.top; oldBodyLeft = body.style.left; oldBodyRight = body.style.right; oldBodyWidth = body.style.width; oldBodyMaxWidth = body.style.maxWidth; oldBodyOverflow = body.style.overflow; oldBodyOverflowX = body.style.overflowX; oldHtmlOverflow = html.style.overflow; oldHtmlOverflowX = html.style.overflowX; html.classList.add('bap-stripe-v7-open'); body.classList.add('bap-stripe-v7-open'); html.style.overflow = 'hidden'; html.style.overflowX = 'hidden'; body.style.position = 'fixed'; body.style.top = '-' + savedScrollY + 'px'; body.style.left = '0'; body.style.right = '0'; body.style.width = '100%'; body.style.maxWidth = '100%'; body.style.overflow = 'hidden'; body.style.overflowX = 'hidden'; } function restorePage() { const html = document.documentElement; const body = document.body; const scrollY = savedScrollY; html.classList.remove('bap-stripe-v7-open'); body.classList.remove('bap-stripe-v7-open'); body.style.position = oldBodyPosition; body.style.top = oldBodyTop; body.style.left = oldBodyLeft; body.style.right = oldBodyRight; body.style.width = oldBodyWidth; body.style.maxWidth = oldBodyMaxWidth; body.style.overflow = oldBodyOverflow; body.style.overflowX = oldBodyOverflowX; html.style.overflow = oldHtmlOverflow; html.style.overflowX = oldHtmlOverflowX; window.scrollTo(0, scrollY); } /* * Use the REAL visual viewport dimensions. * * Phone sizing: * - leaves roughly 20px each side on an iPhone 13-sized viewport * - never goes below 280px wide * * Larger screens: * - capped at 420px */ function sizeAndPositionModal() { if (!activeFieldset) { return; } const html = document.documentElement; const vv = window.visualViewport; const innerWidth = window.innerWidth || html.clientWidth || 320; const innerHeight = window.innerHeight || html.clientHeight || 480; const screenWidth = (window.screen && window.screen.width) ? window.screen.width : innerWidth; const screenHeight = (window.screen && window.screen.height) ? window.screen.height : innerHeight; const shortScreenEdge = Math.min(screenWidth, screenHeight); const isPhoneSized = shortScreenEdge <= 600; /* * V13 WIDTH * * Phones: use the larger of the browser viewport and CSS screen width, * then leave a clear equal margin on both sides. * * Tablets/desktops: use the browser viewport and cap the popup so it * stays professional rather than becoming too wide. */ const horizontalSpace = isPhoneSized ? Math.max(innerWidth, screenWidth) : innerWidth; let modalWidth; if (isPhoneSized) { const sideGap = horizontalSpace <= 360 ? 14 : 18; modalWidth = horizontalSpace - (sideGap * 2); modalWidth = Math.min(modalWidth, 430); } else { modalWidth = Math.min(520, innerWidth - 40); } modalWidth = Math.max(280, modalWidth); /* * Use the visible browser viewport for vertical space. * visualViewport is useful here because Safari's browser chrome * changes the usable height while scrolling/typing. */ const visibleHeight = vv ? vv.height : innerHeight; const visibleTop = vv ? vv.offsetTop : 0; const maxHeight = Math.max(220, visibleHeight - 32); activeFieldset.style.setProperty('width', modalWidth + 'px', 'important'); activeFieldset.style.setProperty('max-width', modalWidth + 'px', 'important'); activeFieldset.style.setProperty('max-height', maxHeight + 'px', 'important'); /* * KEY V13 CHANGE: * * Do not assume CSS left/top coordinates correspond to the screen. * First place the popup at 0/0, measure where the browser/theme * ACTUALLY rendered it, then shift it by the measured difference. * * This centres the popup according to its real on-screen rectangle, * even when a WordPress/theme wrapper creates an unexpected * containing block. */ activeFieldset.style.setProperty('left', '0px', 'important'); activeFieldset.style.setProperty('top', '0px', 'important'); requestAnimationFrame(function () { if (!activeFieldset) { return; } const rect = activeFieldset.getBoundingClientRect(); const targetWidth = isPhoneSized ? Math.max(innerWidth, screenWidth) : innerWidth; const desiredLeft = Math.max(8, (targetWidth - rect.width) / 2); let desiredTop; if (rect.height >= visibleHeight - 24) { desiredTop = visibleTop + 12; } else { desiredTop = visibleTop + Math.max(12, (visibleHeight - rect.height) / 2); } /* * Because rect.left / rect.top tell us where 0/0 actually landed, * subtract that offset to compensate for the containing block. */ const correctedLeft = desiredLeft - rect.left; const correctedTop = desiredTop - rect.top; activeFieldset.style.setProperty('left', correctedLeft + 'px', 'important'); activeFieldset.style.setProperty('top', correctedTop + 'px', 'important'); /* * One second measurement pass removes any remaining rounding / * browser-chrome discrepancy. */ requestAnimationFrame(function () { if (!activeFieldset) { return; } const rect2 = activeFieldset.getBoundingClientRect(); const deltaX = desiredLeft - rect2.left; const deltaY = desiredTop - rect2.top; if (Math.abs(deltaX) > 0.5) { const currentLeft = parseFloat(activeFieldset.style.left) || 0; activeFieldset.style.setProperty( 'left', (currentLeft + deltaX) + 'px', 'important' ); } if (Math.abs(deltaY) > 0.5) { const currentTop = parseFloat(activeFieldset.style.top) || 0; activeFieldset.style.setProperty( 'top', (currentTop + deltaY) + 'px', 'important' ); } }); }); } function keyboardIsOpen() { const vv = window.visualViewport; if (!vv || !baselineVisualHeight) { return false; } /* * If the visible viewport has shrunk substantially from the height * recorded when the popup first opened, treat that as the iOS/Android * on-screen keyboard being open. */ return vv.height < (baselineVisualHeight * 0.82); } function scheduleResize() { /* * V15 KEYBOARD RULE: * While the numeric keyboard is open, DO NOT reposition the modal. * * Earlier versions reacted to visualViewport changes while Stripe * moved focus from card number to expiry/CVC, which made the popup * jump down toward the footer. V15 deliberately leaves left/top/width * untouched until the keyboard closes. */ if (activeFieldset && keyboardIsOpen()) { return; } window.clearTimeout(resizeTimer); resizeTimer = window.setTimeout(function () { if (!activeFieldset || keyboardIsOpen()) { return; } sizeAndPositionModal(); }, 60); } function clearMeasuredStyles(fieldset) { if (!fieldset) { return; } fieldset.style.removeProperty('width'); fieldset.style.removeProperty('max-width'); fieldset.style.removeProperty('left'); fieldset.style.removeProperty('top'); fieldset.style.removeProperty('max-height'); } function openModal(fieldset, stripeBox) { if (!fieldset || !stripeBox || fieldset.classList.contains('bap-stripe-v7-modal')) { return; } activeFieldset = fieldset; activeStripeBox = stripeBox; baselineVisualHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight; buildModalUi(fieldset); createBackdrop(); stripeBox.classList.remove('bap-stripe-v7-trigger'); neutraliseAncestors(fieldset); freezePage(); fieldset.classList.add('bap-stripe-v7-modal'); fieldset.setAttribute('role', 'dialog'); fieldset.setAttribute('aria-modal', 'true'); fieldset.setAttribute('aria-labelledby', 'bap-stripe-v7-title'); backdrop.hidden = false; backdrop.setAttribute('aria-hidden', 'false'); sizeAndPositionModal(); requestAnimationFrame(function () { sizeAndPositionModal(); requestAnimationFrame(function () { sizeAndPositionModal(); const closeButton = fieldset.querySelector('.bap-v7-close'); if (closeButton) { try { closeButton.focus({ preventScroll: true }); } catch (e) { closeButton.focus(); } } }); }); } function closeModal() { if (!activeFieldset) { return; } const fieldset = activeFieldset; const stripeBox = activeStripeBox; fieldset.classList.remove('bap-stripe-v7-modal'); fieldset.removeAttribute('role'); fieldset.removeAttribute('aria-modal'); fieldset.removeAttribute('aria-labelledby'); clearMeasuredStyles(fieldset); if (stripeBox && document.contains(stripeBox)) { stripeBox.classList.add('bap-stripe-v7-trigger'); } if (backdrop) { backdrop.hidden = true; backdrop.setAttribute('aria-hidden', 'true'); } activeFieldset = null; activeStripeBox = null; baselineVisualHeight = 0; restoreAncestors(); restorePage(); } function initialise() { const fieldset = document.getElementById('rtcl-stripe-cc-form'); const stripeBox = document.getElementById('stripe-card-element'); if (!fieldset || !stripeBox || !fieldset.contains(stripeBox)) { return; } buildModalUi(fieldset); createBackdrop(); if (!fieldset.classList.contains('bap-stripe-v7-modal')) { stripeBox.classList.add('bap-stripe-v7-trigger'); } if (stripeBox.dataset.bapV7Ready === '1') { return; } stripeBox.dataset.bapV7Ready = '1'; stripeBox.addEventListener('click', function (event) { if (!fieldset.classList.contains('bap-stripe-v7-modal')) { event.preventDefault(); openModal(fieldset, stripeBox); } }); } document.addEventListener('keydown', function (event) { if (event.key === 'Escape' && activeFieldset) { event.preventDefault(); closeModal(); } }); window.addEventListener('resize', scheduleResize, { passive: true }); window.addEventListener('orientationchange', scheduleResize, { passive: true }); if (window.visualViewport) { window.visualViewport.addEventListener('resize', scheduleResize, { passive: true }); } if (document.readyCounty === 'loading') { document.addEventListener('DOMContentLoaded', initialise); } else { initialise(); } const observer = new MutationObserver(function () { if (activeFieldset && !document.contains(activeFieldset)) { clearMeasuredStyles(activeFieldset); activeFieldset = null; activeStripeBox = null; baselineVisualHeight = 0; if (backdrop) { backdrop.hidden = true; backdrop.setAttribute('aria-hidden', 'true'); } restoreAncestors(); restorePage(); } initialise(); }); observer.observe(document.documentElement, { childList: true, subtree: true }); })();