Peru created the better chances throughout the 90 minutes and missed a penalty through Christian Cueva, but a second-half strike from Yussuf Poulsen extended Denmark's unbeaten run to 16 matches, as well as ending Peru's 15-game undefeated streak.
Peru began the fixture at a fast pace and they got their first shot on target as early as the eighth minute through Yoshimar Yotun, whose 25-yard strike went straight into the hands of Kasper Schmeichel.
Edison Flores also tried his luck from distance, with an effort going well over the crossbar, before Andre Carrillo cut inside onto his left foot before forcing a solid intervention out of Schmeichel.
Denmark slowly grew into the contest but their sole chance in the first half-hour came through Thomas Delaney, who fired well off target from 30 yards out.
Lasse Schone - who had replaced the injured William Kvist - also saw a speculative half-volley comfortably dealt with by Pedro Gallese and at a time when it appeared that the end of the 45 minutes would be reached without incident, Peru were given a penalty via VAR.
The referee initially waved Peru's appeals away after Cueva appeared to be tripped by Poulsen but as play continued, the decision was being reviewed and the official eventually halted the action to point to the spot.
However, Cueva wasted the chance, stuttering on his run-up and then blazing his effort about three yards over the crossbar despite sending Schmeichel the wrong way.
Both teams continued to show ambition after the restart without being able to create a meaningful chance but just before the hour mark, Denmark opened the scoring through Poulsen.
Peru gave the ball away on the halfway line and Christian Eriksen took full advantage as the ball was played through to Poulsen who slotted a shot inside the near post from 12 yards out.
A minute after going behind, Peru almost found an equaliser through Flores but despite having time and space to get a shot away on the left-hand side of the penalty area, the winger put his shot too close to Schmeichel.
Ricardo Gareca opted to introduce Peru's record goalscorer Paolo Guerrero and the veteran almost made an instant impact, but the striker's header from 10 yards was sent straight into Schmeichel's hands.
Peru were beginning to dominate but Denmark were somehow managing to remain ahead, with Jefferson Farfan failing to get the decisive touch from two yards out and Denmark's Henrik Dalsgaard having to head from under his own crossbar.
With 11 minutes left, Guerrero nearly scored one of the goals of the early stages of this tournament with the Flamengo forward sending a back-heel towards the far bottom corner from 10 yards, only to watch on as the ball went agonisingly wide with Schmeichel beaten.
Another chance was squandered soon afterwards when Farfan was teed up on the penalty spot but despite making a clean connection with his shot, Schmeichel managed to stick out a leg to keep the ball out.
Eriksen squandered a late chance for Denmark with Gallese making the save from 14 yards, but Denmark held on for a win which could prove decisive come the end of the month.
PERU (4-3-3): Gallese; Advincula, Ramos, Rodriguez, Trauco; Yotun, Tapia (Aquino 87'), Cueva; Carrillo, Farfan (Ruidiaz 85'), Flores (Guerrero 62')
DENMARK (4-3-3): Schmeichel; Dalsgaard, Kjaer, Christensen (M.Jorgensen 81'), Larsen; Kvist (Schone 36'), Delaney, Eriksen; Poulsen, N.Jorgensen, Sisto (Braithwaite 67')