當曹、劉作戰正酣之時,袁紹謀士許攸建議袁紹“舉軍而襲其後”,但袁紹以兒子有病為辭拒絕采納,致使曹操從容擊敗劉備回軍官渡。
建安四年,五月,袁紹派陳琳書寫檄文並發布,檄文中把曹操罵得差點無法忍受。
中旬,袁紹進軍黎陽,企圖渡河尋求與曹軍主力決戰。他首先派顏良進攻白馬的東郡太守劉延,企圖奪取黃河南岸要點,以保障主力渡河。曹操為爭取主動,求得初戰的勝利,親自率兵北上解救白馬之圍。
此時謀士程昱認為袁紹兵多,建議聲東擊西,分散其兵力,先引兵至延津,偽裝渡河攻袁後方,使袁紹分兵向西,然後遣輕騎迅速襲擊進攻白馬的袁軍,攻其不備,定可擊敗顏良。
曹操采納了這一建議,袁紹果然分兵延津。曹操乃乘機率輕騎,派曹洪、關羽為前鋒,急趨白馬。關羽迅速迫近顏良軍,顏良倉促應戰被斬殺,袁軍潰敗。
曹操解了白馬之圍後,遷徙白馬的百姓沿黃河向西撤退,袁紹率軍渡河追擊,軍至延津南,派大將文醜與韓猛繼續率兵追擊曹軍。
曹操當時隻有騎兵不過千,駐於南阪(在白馬南)下,而袁軍達五六千騎,尚有上萬步兵在後跟進。曹操令士卒解鞍放馬,並故意將輜重丟棄道旁,以誘惑敵軍。
袁軍一見果然中計,紛紛爭搶財物。曹操突然發起攻擊,終於擊敗袁軍,殺了文醜,擊退韓猛,順利退回官渡。
袁軍初戰失利,但兵力仍占絕對優勢。五月下旬,進軍陽武,準備南下進攻許昌。六月初,袁軍主力接近官渡,依沙堆立營,東西寬約數十裏。曹操也立營與袁軍對峙。短短幾天內,曹軍一度主動出擊,卻是不能獲勝,無奈隻能退回營壘堅守。
袁紹構築樓櫓,堆土如山,用箭俯射曹營。曹軍製作了一種拋石裝置的霹靂車,發石擊毀了袁軍所築的樓櫓。袁軍又掘地道進攻,曹軍也在營內掘長塹相抵抗。
雙方相持十餘天,曹操外境困難,前方兵少糧缺,士卒疲乏,後方也不穩固,曹操幾乎失去堅守的信心。就在這時,鬼才郭嘉向他提出“曹操十勝,袁紹十敗”的論斷後,曹操這才決心堅持危局,加強防守。
曹操命負責後勤補給的任峻采取十路縱隊為一部,縮短運輸隊的前後距離,並用複陣(兩列陣),加強護衛,防止袁軍襲擊;另一方麵積極尋求和捕捉戰機,擊敗袁軍,不久派樂進、史渙截擊、燒毀袁軍數千輛糧車,增加了袁軍的困難。
六月中旬,袁紹又派車運糧,並令淳於瓊率兵萬人護送,屯積在袁軍大營以北約二十公裏的故市、烏巢。恰在這時,袁紹第一謀士許攸居然投降了曹操,建議曹操輕兵奇襲烏巢,燒其輜重。
曹操立即付諸實行,留曹洪、荀攸守營壘,親自率領步騎五千兵馬,冒用袁軍旗號,銜枚縛馬口,每人帶一束柴草,利用夜暗走小路偷襲烏巢。到達後立即圍攻放火。袁紹聽說曹操襲擊烏巢,又作出錯誤處置,隻派一部兵力救援烏巢,用主力猛攻官渡曹軍營壘。