Kansas City won its third in a row and the Royals handed the Astros their 40th loss in 62 games this season.
Jason Castro doubled in a run in the seventh to lift Houston into a 2-2 tie, but the Royals regained the lead in the eighth against Wesley Wright (0-2).
Eric Hosmer singled to open the inning and with one out Butler sent a double to left that scored the go-ahead run. Butler then came in on a two-out double by David Lough.
Reliever Kelvin Herrera (3-4) was credited with the win after retiring the side in order in the eighth. Greg Holland also turned in a perfect ninth inning for his 11th save.
Kansas City starter James Shields limited Houston to two runs through seven innings despite allowing a dozen base runners.