חניבעל ניסה להתגרות בפאביוס על ידי כך שפלש לקמפניה ופשט על הערים סביב המושבה הרומית בנבנטום (ב-בנוונטו המודרנית). על פי פוליביוס, חניבעל לכד עיר בשם "ונוסיה" (Venosia). מיקומה של עיר זו אינו ידוע. ליוויוס מזכיר שחניבעל כבש עיר אחרת בשם "טלסיה" (Telesia), שנמצאה כ-36 ק"מ מבנבנטום. פאביוס כדרכו לא הגיב. חניבעל שראה זאת, החליט לפשוט על אזור "אגר פלרנוס", שהיה מקום פורה ועשיר. חניבעל הסיק שגם אם פאביוס לא יתקוף, לפחות בעלות הברית של רומא יבינו שרומא אינה יכולה לספק להם הגנה ויערקו לצד שלו. הוא אסף כמות גדולה מאוד של שלל, ורצה להביא אותו אל מקום שבו יוכל לאחסן אותו לקראת החורף המתקרב. הוא טעה בדרכו חזרה, ופאביוס לא עמד בפיתוי וניסה לארוב לו בקרב אגר פלרנוס. חניבעל הצליח להתחמק מהמלכודת של פאביוס בדרך מקורית ולא צפויה, הוא שיגר עדר שוורים על החיילים הרומאיים.
המאורע הכפיש לחלוטין את שמו של פאביוס ברומא. חניבעל ניצל זאת, וכדי להגביר את הזעם על פאביוס, הורה לחייליו לשרוף את כל האדמות הרומאיות שייתקלו בהן פרט לאדמותיו של פאביוס, ואף העמיד עליהן שומרים כדי שלא יגנבו מהן דבר. במקביל, הסכים פאביוס לעשות הסכם החלפת שבויים עם חניבעל. על פי ההסכם, כנגד כל שבוי רומאי יקבל חניבעל שבוי קרתגי, ואם יהיו לצד מסוים יותר שבויים מלצד השני אז כנגד כל שבוי ישלם הצד השני 250 דינרים. לחניבעל היו 240 שבויים יותר מלפאביוס, אולם הסנאט, שכעס על ההסכם, סירב לשלוח את הסכום לפדיונם. בלית ברירה שלח פאביוס את בנו לרומא כדי שימכור את קרקעותיו ובכסף הזה פדה את השבויים.
חניבעל חיפש מקלט לחורף של שנת 217 לפנה"ס. לצורך כך הוא בחר בעיר גרוניום (Geronium) באזור מוליזה של ימינו. לאחר שנכשל משא ומתן עם התושבים, הטיל עליה חניבעל מצור וכבש אותה. הוא הרג את התושבים, אולם השאיר על כנם את הבתים והחומות כי תכנן להשתמש בהם. הוא הקים מחנה מול העיר, ושלח בכל יום שני שלישים מהצבא לאסוף תבואה ושליש אחד השאיר לשמירה. בינתיים פאביוס נקרא חזרה לרומא, על פי המקורות לצורך תפקידים דתיים, אולם ככל הנראה יזם את חזרתו כדי לשמור על מעמדו הפוליטי בעיר. הוא הותיר את מינוקיוס כמפקד בשטח, והורה לו לא לתקוף בשום מחיר. אולם מינוקיוס לא שעה להזהרות הדיקטטור ותכנן לתקוף את מחנהו של חניבעל. חניבעל ראה את מינוקיוס ומיהר לעבור אל גבעה סמוכה עם מרבית הצבא, אולם בהדרגה נאלץ להורות לחייליו לחזור וללקט תבואה, שכן חשש שבמהלך החורף לא יהיה לו די אספקה. מינוקיוס ניצל זאת ושלח את פרשיו נגד הלקטים והורה להם לא לקחת שבויים. את שאר הצבא שלח נגד מחנהו של חניבעל, שהתגונן בקושי. הוא ניצל רק הודות לסיוע מהיר שהביא עזרובעל, ומינוקיוס נסוג חזרה למחנה שלו. אולם למרות זאת, אבדות הקרתגים היו רבות בעוד אבדות הרומאים קלושות. חניבעל עזב את המחנה על הגבעה וחזר לגרוניום, ומאז נזהר יותר באיסוף התבואה.
כששמע הניצחון הזעום הגיע לרומא, שררה שמחה גדולה בעיר, שכן היה זה הניצחון הראשון מאז הגיע חניבעל לאיטליה. קרנו של פאביוס הלכה וירדה בעוד קרנו של מינוקיוס עלתה. הוחלט למנות אותו כ"דיקטטור עמית", דבר שלא נעשה מעולם ברומא. הוא דרש בתחילה מפאביוס שהם יתחלפו בפיקוד לסירוגין, אולם פאביוס סירב ונתן למינוקיוס לפקד על שני לגיונות ועל חילות העזר של בעלי הברית, בעוד הוא עצמו פיקד על שני לגיונות נוספים. הם חנו במרחק של חצי קילומטר זה מזה. חניבעל תחקר את שבוייו ולמד להכיר את אופיו של מינוקיוס. הוא תכנן להציב לו מלכודת באופן הבא: בין המחנה של חניבעל לזה של מינוקיוס הפרידה תלולית, שהיוותה עמדה אסטרטגית חשובה. חניבעל תכנן לתפוס אותה, אולם ידע שמינוקיוס ימנע ממנו לעשות זאת. על כן החביא רבים מחייליו באזור התלולית, ושלח אחרים כביכול לכבוש אותה. מינוקיוס שראה זאת, מיהר לתקוף, אולם אז חייליו של חניבעל זינקו מן המארב. חייליו של מינוקיוס פנו לסגת, אולם פרשיו של חניבעל טבחו בהם ללא רחם. פאביוס השקיף כל העת בדאגה על הנעשה ולבסוף הורה לחייליו להצטרף למערכה. בלית ברירה, הורה חניבעל לחייליו לסגת. הוא חזר אל המחנה וגם הרומאים עשו כמוהו. לאחר הקרב ביצר חניבעל את מחנהו, והעביר את החורף בשקט.
קרב קאנאי ותוצאותיו.
עם הגיע האביב של שנת 216 לפנה"ס, התפטרו פאביוס ומינוקיוס ממשרותיהם, וכקונסולים של אותה שנה נבחרו לוקיוס אמיליוס פאולוס וגאיוס טרנטיוס וארו. סרוויליוס ומרקוס רגולוס התמנו לפרו קונסולים, וההוראה שקיבלו הייתה להתגרות בצבאו של חניבעל אך לא לתקוף אותו ישירות. חניבעל מצידו עזב את גרוניום וכבש את מצודת קאנאי, ששכנה במיקום אסטרטגי והוא מצא בה גם אספקה בשפע. הסנאט הרומי החליט לנטוש את אסטרטגיית ההתשה של פאביוס ולחתור לקרב הכרעה נגד צבאו במטרה להשמיד אותו לחלוטין. לפי התיאור של ליוויוס ופולביוס, מבין שני הקונסולים הרומיים, וארו היה הלהוט לכך ביותר. רומא גייסה צבא אדיר. לפי פוליביוס, הצבא הרומאי כלל 8 לגיונות ועוד 8 לגיונות של בעלי הברית, סה"כ 80,000 רגלים ו-6,000 פרשים, בעוד שלפי ליוויוס, הוא כלל 4 לגיונות ועוד 4 של בעלי הברית, שתוגברו מעט וכללו 49,000 רגלים ו-6,000 פרשים. מרבית החוקרים מאמצים את הערכתו של פוליביוס ביחס לגודלו של הצבא הרומאי. צבאו של חניבעל כלל ערב הקרב בערך 40,000 רגלים ו-10,000 פרשים, לאחר שגודלו תפח הודות לגאלים מצפון איטליה, שהצטרפו אליו לאחר הניצחון בקרב טראסימנוס.
הקרב נערך ככל הנראה באזור הנהר אופידוס (בשמו המודרני אופנטו) ב-2 באוגוסט 216 לפנה"ס. פוליביוס וליוויוס טוענים שווארו חסר הניסיון הצבאי פיקד באותו יום על הצבא, אולם ככל הנראה ההוראה לצאת לקרב הגיעה בלאו הכי מהסנאט, כך שלדבר אין חשיבות רבה. הקרב נפתח בהסתערות הפרשים של חניבעל, בפיקוד עזרובעל ומהרבעל, שהוצבו בשני האגפים של צבאו, על כנפות הפרשים של הצבא הרומאי. במקביל, החלו הלגיונות הרומיים במרכז, לתקוף את חיל הרגלים הקרתגי, שנערך בצורת חצי סהר שקדקודו פונה כלפי הצבא הרומאי. היתרון המספרי של הרומאים ואיכות כלי נשקם גרמו לכך, שהרגלים קלי החימוש של חניבעל שניצבו מולם, נדחקו בהדרגה לאחור עד שכיוון חצי הסהר התהפך, והמערך הקרתגי במרכז היה קרוב לשבירה. בשלב זה פתחו הרגלים הכבדים של חניבעל, שכללו בעיקר חיילים לוביים חמושים היטב, והוצבו באגפים של הרגלים הקלים במרכז, בהסתערות על האגפים של הלגיונות הרומיים, שנחשפו עקב התקדמותם לעומק המערך הקרתגי. ההסתערות הבלתי צפויה, שנפתחה בהטלת מטח של רמחים, גרמה לבלבול ולכאוס בשורות הלגיונות הרומיים. בשלב זה הצטרפו למתקפה גם פרשיו של חניבעל, שחזרו לשדה הקרב לאחר שסיימו להביס את כנפות הפרשים הרומיים, תקפו את חיל הרגלים הרומי מעורפו והשלימו את כיתור הצבא הרומאי. מה שהתרחש בהמשך דמה יותר לטבח מאשר לקרב. החיילים הרומיים, שנדחקו לתוך שטח צר והותקפו מכל העברים, לא יכלו לתמרן בגלל הצפיפות הרבה, ונטבחו ללא רחם.
הניצחון הקרתגי היה שלם. בין 50 אלף ל-70 אלף רומאים נהרגו בקרב, ביניהם כמה מאויביו המושבעים של חניבעל: מינוקיוס, הדיקטטור לשעבר, פאולוס, הקונסול השני של אותה שנה, וכן 80 סנטורים ו-29 טריבונים צבאיים. הניצחון המכריע של חניבעל בקרב, על אף הנחיתות המספרית הניכרת של צבאו, והטקטיקה המבריקה בה השתמש במהלך הקרב, היקנו לו מקום של כבוד בקרב המצביאים הגדולים בהיסטוריה.
לאחר הקרב, חלק מהמצביאים הקרתגים ובראשם מהרבעל, יעצו לחניבעל ללכוד את רומא חסרת המגן בהתקפה מהירה, תוך ניצול מהירות התנועה של פרשיו. אולם בצעד שנותר שנוי במחלוקת עד ימינו, חניבעל סרב. לא ברור מדוע סירב חניבעל לתקוף את רומא לאחר שעיקר צבאה הושמד בשדה הקרב והעיר נותרה חסרת הגנה כמעט. יש לזכור שצבאו ספג אף הוא אבדות כבדות במהלך קרב קאנאי (כ-8,000 הרוגים ומספר לא ידוע של פצועים) ונזקק לזמן להתאוששות. החוקר ג'ון שין (John Shean) מעריך שמחסור בציוד מצור ובאספקה אילץ את חניבעל לעשות זאת, בעוד הנס דלבריק טוען שמחסור בכוח אדם והצורך של חניבעל להותיר חילות מצב בנקודות שונות, הם אלו שמנעו זאת ממנו. לדעת אדריאן גולדסוורת'י, העובדה שחניבעל סירב לתקוף את רומא מעידה שהוא לא תכנן להרוס את העיר, אלא רק לאלץ אותה לחתום על הסכם שלום נוח לקרתגו. עם זאת, מבקריו של חניבעל טוענים, שהיה לו סיכוי לכבוש את רומא בהתקפה מהירה, תוך ניצול הפאניקה שהתבוסה עוררה בקרב הציבור ברומא, והעובדה ששדרת הפיקוד הרומאית השתבשה לחלוטין עקב אובדן רוב הפיקוד הבכיר של הצבא בשדה הקרב.
לאחר קאנאי.
לאחר קרב קאנאי, בילה חניבעל זמן מסוים באיסוף השלל ובהכרעת כיסי התנגדות רומאיים אחרונים. וארו עצמו נמלט מהקרב עם שבעים פרשים בלבד. כוח רומאי גדול יותר, שכלל מעל 2,000 לגיונרים, נמלט לעיר קנוסיום (קאנוסה המודרנית). מפקדיהם, שסברו שהקיץ הקץ על רומא, תכננו להימלט מחצי האי דרך הים. המזימה נמנעה הודות ליוזמתו של סקיפיו הצעיר, שארגן את חבירת הכוח אל מחנהו של וארו שחזר מובס אל רומא.