8月2日上午双方在坎尼激战。迦太基步兵对罗马步兵进行一定的抗击后,汉尼拔即令预先准备好的500名士兵向罗马方向逃跑,交出自己的剑和矛,假装投降。罗马军把这些投降兵置于阵后并未严加看管,仍集中兵力继续猛攻汉尼拔步兵阵地的中央突出部。在罗马军步兵的强攻下,位于半月形突出部的汉尼拔步兵逐渐后退,使半月形阵势由凸部向敌变成了凹部向敌,从而对罗马军形成了一个口袋形的阵势。汉尼拔见敌人已中圈套,便命令两翼的步兵主力同时夹击罗马军。罗马军遭此不意攻击,阵势顿时大乱。当战至中午时分,东南风大作,大大增加了迦太军杀伤效果。持续的狂风把风沙尘土刮向罗马军队,致使其不能准确使用手中武器,又难于躲避对方投射过来的矛、箭和石头,伤亡惨重。此时此刻,500名诈降的迦太基士兵从身上摸出暗藏的匕首,首先刺死当面的敌人,然后从死者身上拿过武器,在敌军内部横冲直撞,四处冲杀。与此同时,汉尼拔的骑兵也从敌军背后冲杀过来,罗马军深深陷进汉尼拔预设的口袋,内外受击。战至天黑,罗马军被歼6万余人,被俘约1万人,只有1万多人逃走。亲临前线指挥的罗马执政官伊米里亚斯阵亡,此外战死的还有80名元老院议员。全罗马17岁以上的男子有1/5在这场和汉尼拔的战争中丧生。而汉尼拔的军队伤亡仅8000人左右。
此后,在意大利,战争开始陷入一种惰性的状态。直到公元前203年年底,在意大利,没有一位罗马将军在和汉尼拔的战场较量中真正取胜过。而无数的战役只是为汉尼拔的桂冠上增添一道又一道光环。
公元前202年,罗马人终于有一位将军在坎尼战役后敢于在战场上和汉尼拔正面交锋了,并取得了决定性胜利。在扎马战役中,罗马将军大西庇阿打败了汉尼拔,他也因为这一战而名载史册。扎马战役是第二次布匿战争的最后一仗。不久迦太