Heinsberg liegt rund 32 km südwestlich von Mönchengladbach und etwa 35 km nördlich von Aachen am südwestlichen Rand des Rurtales, das sich hier trichterförmig in Richtung zu den Niederlanden weitet. Die Rur ist auf mehreren Kilometern nordöstliche Stadtgrenze zu den Nachbarstädten Hückelhoven und Wassenberg, bevor sie in der Nähe des Ortsteiles Karken über die Staatsgrenze in die Niederlande fließt. Durch das Stadtgebiet zieht auch die bei Kempen in die Rur mündende Wurm. Der höchste Punkt des Stadtgebiets mit 85 m ü. NN befindet sich südlich von Straeten an der Stadtgrenze zu Geilenkirchen, der niedrigste mit 28 m ü. NN nördlich von Karken an der niederländischen Grenze.
Neben Rur und Wurm fließt der Liecker Bach, auch Stadtbach genannt, durch Heinsberg. Sein Quellgebiet liegt bei Oberlieck westlich von Heinsberg, im weiteren Verlauf wird er auch von Quellen nahe dem Klosterhof gespeist. Das im weiteren Verlauf Junge Wurm genannte Gewässer teilt sich zwischen Kempen und Karken in zwei Bachläufe auf. Der rechte Teil fließt in nordnordöstlicher Richtung zur Rur, in die er weniger als einen Kilometer östlich von Karken mündet. Der linke Mühlenbach dagegen fließt am Ostrand von Karken nordnordwestlich parallel zur Rur, vereinigt sich nördlich von Karken an der Wolfhagermühle mit dem Schaafbach, der weiter talab auf niederländischem Gebiet südlich von Vlodrop ebenfalls von links die Rur erreicht.
Der Vongelaaker Bach entspringt im ehemaligen Bruchgelände zwischen Heinsberg und Schafhausen. Er mündet bei Theberath in die Junge Wurm, nach Grundwasserabsenkungen führt er heute kaum noch Wasser.
Bis zum Zweiten Weltkrieg zog durch Heinsberg und seine Innenstadt der Mühlenbach, auch Junge Wurm oder Kleine Wurm genannt, ein im Mittelalter angelegter linksseitiger Kanal, der wurmaufwärts bei Randerath von der Wurm abzweigte. Er zog dann am linken Hangfuß des Wurmtales über Horst, Porselen, Dremmen und Schafhausen in Richtung Heinsberg und trieb mit 26 Metern Gesamtgefälle zwischen Randerath und Karken ein Dutzend Wassermühlen an.[2] Zwischen Schafhausen und Heinsberg verlief er nach der Tranchotschen Kartenaufnahme aus den ersten Jahrzehnten des 19. Jahrhunderts unmittelbar unterhalb des Steilhanges Klevchen und speiste östlich des Kirchberges eine Mühle, die im zwischen den heutigen Straßen Im Klevchen und Schafhausener Straße lag. Sodann trat er zwischen Burgberg und heutiger evangelischer Kirche in das befestigte Stadtgebiet ein, folgte der Josefstraße und trieb danach die ab 1307 urkundlich belegte, der Ecke Josefstraße/Hochstraße gegenüberliegende Stadtmühle an. 1905 wurden deren Stauwerke beseitigt.[3] Unterhalb der Stadtmühle durchquerte die Junge Wurm den Stadtbereich zwischen Apfelstraße und Hochstraße und verließ dann westlich der Ecke Liecker Straße/Stiftsstraße die Stadt in Richtung Norden.[4] Die Bombenangriffe im letzten Weltkrieg zerstörten das Kanalbett im Stadtkern; es ist nicht wieder instand gesetzt worden.
Der Teichbach, auch Erlenbach genannt, ein Mühlenteich, wird bei Linnich aus der Rur abgeleitet, verläuft ein Stück weit am nordöstlichen Rand des heutigen Stadtgebietes entlang und mündet bei Bleckden an der Schanz (Oberbruch) wieder in die Rur.